Skip to content

Commit 5a648bc

Browse files
committed
DATAES-172 - added test to cover geohash prefix
1 parent 6a06bbf commit 5a648bc

File tree

4 files changed

+101
-149
lines changed

4 files changed

+101
-149
lines changed

src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@
2525
import java.util.List;
2626
import java.util.Map;
2727

28+
import org.apache.commons.lang.math.NumberUtils;
2829
import org.elasticsearch.common.lang3.StringUtils;
2930
import org.elasticsearch.common.xcontent.XContentBuilder;
3031
import org.springframework.core.GenericCollectionTypeResolver;
3132
import org.springframework.data.annotation.Transient;
3233
import org.springframework.data.elasticsearch.annotations.*;
3334
import org.springframework.data.elasticsearch.core.completion.Completion;
34-
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
3535
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
3636
import org.springframework.data.mapping.model.SimpleTypeHolder;
3737
import org.springframework.data.util.ClassTypeInformation;
@@ -66,7 +66,7 @@ class MappingBuilder {
6666
public static final String TYPE_VALUE_STRING = "string";
6767
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
6868
public static final String TYPE_VALUE_COMPLETION = "completion";
69-
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix" ;
69+
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix";
7070
public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision";
7171

7272
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
@@ -176,11 +176,16 @@ private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, j
176176

177177
GeoPointField annotation = field.getAnnotation(GeoPointField.class);
178178
if (annotation != null) {
179-
if (annotation.geoHashPrefix())
179+
if (annotation.geoHashPrefix()) {
180180
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PREFIX, true);
181-
182-
if (StringUtils.isNotEmpty(annotation.geoHashPrecision()))
183-
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision());
181+
if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) {
182+
if (NumberUtils.isNumber(annotation.geoHashPrecision())) {
183+
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, Integer.parseInt(annotation.geoHashPrecision()));
184+
} else {
185+
xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision());
186+
}
187+
}
188+
}
184189
}
185190

186191
xContentBuilder.endObject();
@@ -283,33 +288,6 @@ private static void addMultiFieldMapping(XContentBuilder builder, java.lang.refl
283288
builder.endObject();
284289
}
285290

286-
/**
287-
* Facet field for string type, for other types we don't need it(long, int, double, float)
288-
*
289-
* @throws IOException
290-
*/
291-
private static void addFacetMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
292-
builder.startObject(FacetRequest.FIELD_UNTOUCHED)
293-
.field(FIELD_TYPE, TYPE_VALUE_STRING)
294-
.field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED)
295-
.field(FIELD_STORE, true);
296-
builder.endObject();
297-
}
298-
299-
/**
300-
* Sort field for string type, for other types we don't need it(long, int, double, float)
301-
* value of the field should be converted to lowercase and not analise
302-
*
303-
* @throws IOException
304-
*/
305-
private static void addSortMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException {
306-
builder.startObject(FacetRequest.FIELD_SORT)
307-
.field(FIELD_TYPE, TYPE_VALUE_STRING)
308-
.field(FIELD_INDEX, "keyword")
309-
.field(FIELD_STORE, true);
310-
builder.endObject();
311-
}
312-
313291
protected static boolean isEntity(java.lang.reflect.Field field) {
314292
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
315293
Class<?> clazz = getFieldType(field);

src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntityBuilder.java

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.elasticsearch.common.geo.GeoHashUtils;
2626
import org.elasticsearch.index.query.FilterBuilders;
27+
import org.elasticsearch.search.aggregations.AggregationBuilders;
2728
import org.junit.Test;
2829
import org.junit.runner.RunWith;
2930
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,18 +64,36 @@ private void loadClassBaseEntities() {
6364
}
6465

6566
private void loadAnnotationBaseEntities() {
66-
elasticsearchTemplate.deleteIndex(AuthorMarkerAnnotatedEntity.class);
67-
elasticsearchTemplate.createIndex(AuthorMarkerAnnotatedEntity.class);
68-
elasticsearchTemplate.refresh(AuthorMarkerAnnotatedEntity.class, true);
69-
elasticsearchTemplate.putMapping(AuthorMarkerAnnotatedEntity.class);
67+
elasticsearchTemplate.deleteIndex(LocationMarkerEntity.class);
68+
elasticsearchTemplate.createIndex(LocationMarkerEntity.class);
69+
elasticsearchTemplate.refresh(LocationMarkerEntity.class, true);
70+
elasticsearchTemplate.putMapping(LocationMarkerEntity.class);
7071

7172
List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
7273
double[] latLonArray = {0.100000, 51.000000};
7374
String lonLatString = "51.000000, 0.100000";
7475
String geohash = "u1044k2bd6u";
75-
indexQueries.add(new AuthorMarkerAnnotatedEntityBuilder("2").name("Mohsin Husen").location(geohash.substring(0, 5)).additionalLocation(latLonArray).buildIndex());
76-
indexQueries.add(new AuthorMarkerAnnotatedEntityBuilder("1").name("Artur Konczak").location(lonLatString).additionalLocation(latLonArray).buildIndex());
77-
indexQueries.add(new AuthorMarkerAnnotatedEntityBuilder("3").name("Rizwan Idrees").location(geohash).additionalLocation(latLonArray).buildIndex());
76+
LocationMarkerEntity location1 = LocationMarkerEntity.builder()
77+
.id("1").name("Artur Konczak")
78+
.locationAsString(lonLatString)
79+
.locationAsArray(latLonArray)
80+
.locationWithPrefixAsDistance(geohash)
81+
.locationWithPrefixAsLengthOfGeoHash(geohash)
82+
.build();
83+
LocationMarkerEntity location2 = LocationMarkerEntity.builder()
84+
.id("2").name("Mohsin Husen")
85+
.locationAsString(geohash.substring(0, 5))
86+
.locationAsArray(latLonArray)
87+
.build();
88+
LocationMarkerEntity location3 = LocationMarkerEntity.builder()
89+
.id("3").name("Rizwan Idrees")
90+
.locationAsString(geohash)
91+
.locationAsArray(latLonArray)
92+
.locationWithPrefixAsLengthOfGeoHash(geohash)
93+
.build();
94+
indexQueries.add(buildIndex(location1));
95+
indexQueries.add(buildIndex(location2));
96+
indexQueries.add(buildIndex(location3));
7897

7998
elasticsearchTemplate.bulkIndex(indexQueries);
8099
elasticsearchTemplate.refresh(AuthorMarkerEntity.class, true);
@@ -122,9 +141,9 @@ public void shouldFindStringAnnotatedGeoMarkersInRangeForGivenCriteriaQuery() {
122141
//given
123142
loadAnnotationBaseEntities();
124143
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
125-
new Criteria("location").within(new GeoPoint(51.000000, 0.100000), "1km"));
144+
new Criteria("locationAsString").within(new GeoPoint(51.000000, 0.100000), "1km"));
126145
//when
127-
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
146+
List<LocationMarkerEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class);
128147

129148
//then
130149
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
@@ -135,9 +154,9 @@ public void shouldFindDoubleAnnotatedGeoMarkersInRangeForGivenCriteriaQuery() {
135154
//given
136155
loadAnnotationBaseEntities();
137156
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
138-
new Criteria("additionalLocation").within(new GeoPoint(51.001000, 0.10100), "1km"));
157+
new Criteria("locationAsArray").within(new GeoPoint(51.001000, 0.10100), "1km"));
139158
//when
140-
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
159+
List<LocationMarkerEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class);
141160

142161
//then
143162
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
@@ -148,9 +167,9 @@ public void shouldFindAnnotatedGeoMarkersInRangeForGivenCriteriaQuery() {
148167
//given
149168
loadAnnotationBaseEntities();
150169
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
151-
new Criteria("additionalLocation").within("51.001000, 0.10100", "1km"));
170+
new Criteria("locationAsArray").within("51.001000, 0.10100", "1km"));
152171
//when
153-
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
172+
List<LocationMarkerEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class);
154173

155174
//then
156175
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
@@ -161,9 +180,9 @@ public void shouldFindAnnotatedGeoMarkersInRangeForGivenCriteriaQueryUsingGeohas
161180
//given
162181
loadAnnotationBaseEntities();
163182
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
164-
new Criteria("additionalLocation").within("u1044", "1km"));
183+
new Criteria("locationAsArray").within("u1044", "1km"));
165184
//when
166-
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
185+
List<LocationMarkerEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class);
167186

168187
//then
169188
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
@@ -173,9 +192,9 @@ public void shouldFindAnnotatedGeoMarkersInRangeForGivenCriteriaQueryUsingGeohas
173192
public void shouldFindAllMarkersForNativeSearchQuery() {
174193
//Given
175194
loadAnnotationBaseEntities();
176-
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoBoundingBoxFilter("additionalLocation").topLeft(52, -1).bottomRight(50, 1));
195+
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoBoundingBoxFilter("locationAsArray").topLeft(52, -1).bottomRight(50, 1));
177196
//When
178-
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(queryBuilder.build(), AuthorMarkerAnnotatedEntity.class);
197+
List<LocationMarkerEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(queryBuilder.build(), LocationMarkerEntity.class);
179198
//Then
180199
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
181200
}
@@ -228,4 +247,45 @@ public void shouldFindAuthorMarkersInBoxForGivenCriteriaQueryUsingGeoPoints() {
228247
assertThat(geoAuthorsForGeoCriteria3.size(), is(2));
229248
assertThat(geoAuthorsForGeoCriteria3, containsInAnyOrder(hasProperty("name", equalTo("Mohsin Husen")), hasProperty("name", equalTo("Rizwan Idrees"))));
230249
}
250+
251+
@Test
252+
public void shouldFindLocationWithGeoHashPrefix() {
253+
254+
//given
255+
//u1044k2bd6u - with precision = 4 -> u, u1, u10, u104
256+
//u1044k2bd6u - with precision = 5 -> u, u1, u10, u104, u1044
257+
258+
loadAnnotationBaseEntities();
259+
NativeSearchQueryBuilder locationWithPrefixAsDistancePrecision3 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsDistance").geohash("u1044k2bd6u").precision(3));
260+
NativeSearchQueryBuilder locationWithPrefixAsDistancePrecision4 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsDistance").geohash("u1044k2bd6u").precision(4));
261+
NativeSearchQueryBuilder locationWithPrefixAsDistancePrecision5 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsDistance").geohash("u1044k2bd6u").precision(5));
262+
263+
NativeSearchQueryBuilder locationWithPrefixAsLengthOfGeoHashPrecision4 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsLengthOfGeoHash").geohash("u1044k2bd6u").precision(4));
264+
NativeSearchQueryBuilder locationWithPrefixAsLengthOfGeoHashPrecision5 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsLengthOfGeoHash").geohash("u1044k2bd6u").precision(5));
265+
NativeSearchQueryBuilder locationWithPrefixAsLengthOfGeoHashPrecision6 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsLengthOfGeoHash").geohash("u1044k2bd6u").precision(6));
266+
//when
267+
List<LocationMarkerEntity> resultDistancePrecision3 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision3.build(), LocationMarkerEntity.class);
268+
List<LocationMarkerEntity> resultDistancePrecision4 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision4.build(), LocationMarkerEntity.class);
269+
List<LocationMarkerEntity> resultDistancePrecision5 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision5.build(), LocationMarkerEntity.class);
270+
271+
List<LocationMarkerEntity> resultGeoHashLengthPrecision4 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision4.build(), LocationMarkerEntity.class);
272+
List<LocationMarkerEntity> resultGeoHashLengthPrecision5 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision5.build(), LocationMarkerEntity.class);
273+
List<LocationMarkerEntity> resultGeoHashLengthPrecision6 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision6.build(), LocationMarkerEntity.class);
274+
275+
//then
276+
assertThat(resultDistancePrecision3.size(), is(1));
277+
assertThat(resultDistancePrecision4.size(), is(1));
278+
assertThat(resultDistancePrecision5.size(), is(0));
279+
280+
assertThat(resultGeoHashLengthPrecision4.size(), is(2));
281+
assertThat(resultGeoHashLengthPrecision5.size(), is(2));
282+
assertThat(resultGeoHashLengthPrecision6.size(), is(0));
283+
}
284+
285+
private IndexQuery buildIndex(LocationMarkerEntity result) {
286+
IndexQuery indexQuery = new IndexQuery();
287+
indexQuery.setId(result.getId());
288+
indexQuery.setObject(result);
289+
return indexQuery;
290+
}
231291
}
Lines changed: 13 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,63 +15,35 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core.geo;
1717

18+
import lombok.*;
1819
import org.springframework.data.annotation.Id;
1920
import org.springframework.data.elasticsearch.annotations.Document;
2021
import org.springframework.data.elasticsearch.annotations.GeoPointField;
2122

2223
/**
2324
* @author Franck Marchand
2425
*/
26+
@Setter
27+
@Getter
28+
@NoArgsConstructor
29+
@AllArgsConstructor
30+
@Builder
2531
@Document(indexName = "test-geo-index", type = "geo-annotation-point-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
26-
public class AuthorMarkerAnnotatedEntity {
32+
public class LocationMarkerEntity {
2733

2834
@Id
2935
private String id;
3036
private String name;
3137

3238
@GeoPointField
33-
private String location;
39+
private String locationAsString;
3440

3541
@GeoPointField
36-
private double[] additionalLocation;
42+
private double[] locationAsArray;
3743

38-
private AuthorMarkerAnnotatedEntity() {
44+
@GeoPointField(geoHashPrefix = true, geoHashPrecision = "100km")
45+
private String locationWithPrefixAsDistance;
3946

40-
}
41-
42-
public AuthorMarkerAnnotatedEntity(String id) {
43-
this.id = id;
44-
}
45-
46-
public String getId() {
47-
return id;
48-
}
49-
50-
public void setId(String id) {
51-
this.id = id;
52-
}
53-
54-
public String getName() {
55-
return name;
56-
}
57-
58-
public void setName(String name) {
59-
this.name = name;
60-
}
61-
62-
public String getLocation() {
63-
return location;
64-
}
65-
66-
public void setLocation(String location) {
67-
this.location = location;
68-
}
69-
70-
public double[] getAdditionalLocation() {
71-
return additionalLocation;
72-
}
73-
74-
public void setAdditionalLocation(double... additionalLocation) {
75-
this.additionalLocation = additionalLocation;
76-
}
47+
@GeoPointField(geoHashPrefix = true, geoHashPrecision = "5")
48+
private String locationWithPrefixAsLengthOfGeoHash;
7749
}

0 commit comments

Comments
 (0)