From 5a648bcb7a4149cc44fa7409b18448d0a259683e Mon Sep 17 00:00:00 2001 From: Artur Konczak Date: Fri, 18 Sep 2015 16:16:46 +0100 Subject: [PATCH] DATAES-172 - added test to cover geohash prefix --- .../elasticsearch/core/MappingBuilder.java | 44 +++------ .../AuthorMarkerAnnotatedEntityBuilder.java | 58 ------------ .../geo/ElasticsearchTemplateGeoTests.java | 94 +++++++++++++++---- ...dEntity.java => LocationMarkerEntity.java} | 54 +++-------- 4 files changed, 101 insertions(+), 149 deletions(-) delete mode 100644 src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntityBuilder.java rename src/test/java/org/springframework/data/elasticsearch/core/geo/{AuthorMarkerAnnotatedEntity.java => LocationMarkerEntity.java} (60%) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java index 1f0fce5c2..760049eae 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java @@ -25,13 +25,13 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.apache.commons.lang.math.NumberUtils; import org.elasticsearch.common.lang3.StringUtils; import org.elasticsearch.common.xcontent.XContentBuilder; import org.springframework.core.GenericCollectionTypeResolver; import org.springframework.data.annotation.Transient; import org.springframework.data.elasticsearch.annotations.*; import org.springframework.data.elasticsearch.core.completion.Completion; -import org.springframework.data.elasticsearch.core.facet.FacetRequest; import org.springframework.data.elasticsearch.core.geo.GeoPoint; import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.util.ClassTypeInformation; @@ -66,7 +66,7 @@ class MappingBuilder { public static final String TYPE_VALUE_STRING = "string"; public static final String TYPE_VALUE_GEO_POINT = "geo_point"; public static final String TYPE_VALUE_COMPLETION = "completion"; - public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix" ; + public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix"; public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision"; private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder(); @@ -176,11 +176,16 @@ class MappingBuilder { GeoPointField annotation = field.getAnnotation(GeoPointField.class); if (annotation != null) { - if (annotation.geoHashPrefix()) + if (annotation.geoHashPrefix()) { xContentBuilder.field(TYPE_VALUE_GEO_HASH_PREFIX, true); - - if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) - xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision()); + if (StringUtils.isNotEmpty(annotation.geoHashPrecision())) { + if (NumberUtils.isNumber(annotation.geoHashPrecision())) { + xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, Integer.parseInt(annotation.geoHashPrecision())); + } else { + xContentBuilder.field(TYPE_VALUE_GEO_HASH_PRECISION, annotation.geoHashPrecision()); + } + } + } } xContentBuilder.endObject(); @@ -283,33 +288,6 @@ class MappingBuilder { builder.endObject(); } - /** - * Facet field for string type, for other types we don't need it(long, int, double, float) - * - * @throws IOException - */ - private static void addFacetMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException { - builder.startObject(FacetRequest.FIELD_UNTOUCHED) - .field(FIELD_TYPE, TYPE_VALUE_STRING) - .field(FIELD_INDEX, INDEX_VALUE_NOT_ANALYZED) - .field(FIELD_STORE, true); - builder.endObject(); - } - - /** - * Sort field for string type, for other types we don't need it(long, int, double, float) - * value of the field should be converted to lowercase and not analise - * - * @throws IOException - */ - private static void addSortMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation) throws IOException { - builder.startObject(FacetRequest.FIELD_SORT) - .field(FIELD_TYPE, TYPE_VALUE_STRING) - .field(FIELD_INDEX, "keyword") - .field(FIELD_STORE, true); - builder.endObject(); - } - protected static boolean isEntity(java.lang.reflect.Field field) { TypeInformation typeInformation = ClassTypeInformation.from(field.getType()); Class clazz = getFieldType(field); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntityBuilder.java b/src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntityBuilder.java deleted file mode 100644 index d28143216..000000000 --- a/src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntityBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.elasticsearch.core.geo; - -import org.springframework.data.elasticsearch.core.query.IndexQuery; - -/** - * @author Artur Konczak - * @author Mohsin Husen - */ - -public class AuthorMarkerAnnotatedEntityBuilder { - - private AuthorMarkerAnnotatedEntity result; - - public AuthorMarkerAnnotatedEntityBuilder(String id) { - result = new AuthorMarkerAnnotatedEntity(id); - } - - public AuthorMarkerAnnotatedEntityBuilder name(String name) { - result.setName(name); - return this; - } - - public AuthorMarkerAnnotatedEntityBuilder location(String location) { - result.setLocation(location); - return this; - } - - public AuthorMarkerAnnotatedEntityBuilder additionalLocation(double... location) { - result.setAdditionalLocation(location); - return this; - } - - public AuthorMarkerAnnotatedEntity build() { - return result; - } - - public IndexQuery buildIndex() { - IndexQuery indexQuery = new IndexQuery(); - indexQuery.setId(result.getId()); - indexQuery.setObject(result); - return indexQuery; - } -} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java b/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java index 2d988542d..2b78cb767 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/geo/ElasticsearchTemplateGeoTests.java @@ -24,6 +24,7 @@ import java.util.List; import org.elasticsearch.common.geo.GeoHashUtils; import org.elasticsearch.index.query.FilterBuilders; +import org.elasticsearch.search.aggregations.AggregationBuilders; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -63,18 +64,36 @@ public class ElasticsearchTemplateGeoTests { } private void loadAnnotationBaseEntities() { - elasticsearchTemplate.deleteIndex(AuthorMarkerAnnotatedEntity.class); - elasticsearchTemplate.createIndex(AuthorMarkerAnnotatedEntity.class); - elasticsearchTemplate.refresh(AuthorMarkerAnnotatedEntity.class, true); - elasticsearchTemplate.putMapping(AuthorMarkerAnnotatedEntity.class); + elasticsearchTemplate.deleteIndex(LocationMarkerEntity.class); + elasticsearchTemplate.createIndex(LocationMarkerEntity.class); + elasticsearchTemplate.refresh(LocationMarkerEntity.class, true); + elasticsearchTemplate.putMapping(LocationMarkerEntity.class); List indexQueries = new ArrayList(); double[] latLonArray = {0.100000, 51.000000}; String lonLatString = "51.000000, 0.100000"; String geohash = "u1044k2bd6u"; - indexQueries.add(new AuthorMarkerAnnotatedEntityBuilder("2").name("Mohsin Husen").location(geohash.substring(0, 5)).additionalLocation(latLonArray).buildIndex()); - indexQueries.add(new AuthorMarkerAnnotatedEntityBuilder("1").name("Artur Konczak").location(lonLatString).additionalLocation(latLonArray).buildIndex()); - indexQueries.add(new AuthorMarkerAnnotatedEntityBuilder("3").name("Rizwan Idrees").location(geohash).additionalLocation(latLonArray).buildIndex()); + LocationMarkerEntity location1 = LocationMarkerEntity.builder() + .id("1").name("Artur Konczak") + .locationAsString(lonLatString) + .locationAsArray(latLonArray) + .locationWithPrefixAsDistance(geohash) + .locationWithPrefixAsLengthOfGeoHash(geohash) + .build(); + LocationMarkerEntity location2 = LocationMarkerEntity.builder() + .id("2").name("Mohsin Husen") + .locationAsString(geohash.substring(0, 5)) + .locationAsArray(latLonArray) + .build(); + LocationMarkerEntity location3 = LocationMarkerEntity.builder() + .id("3").name("Rizwan Idrees") + .locationAsString(geohash) + .locationAsArray(latLonArray) + .locationWithPrefixAsLengthOfGeoHash(geohash) + .build(); + indexQueries.add(buildIndex(location1)); + indexQueries.add(buildIndex(location2)); + indexQueries.add(buildIndex(location3)); elasticsearchTemplate.bulkIndex(indexQueries); elasticsearchTemplate.refresh(AuthorMarkerEntity.class, true); @@ -122,9 +141,9 @@ public class ElasticsearchTemplateGeoTests { //given loadAnnotationBaseEntities(); CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery( - new Criteria("location").within(new GeoPoint(51.000000, 0.100000), "1km")); + new Criteria("locationAsString").within(new GeoPoint(51.000000, 0.100000), "1km")); //when - List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class); + List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class); //then assertThat(geoAuthorsForGeoCriteria.size(), is(3)); @@ -135,9 +154,9 @@ public class ElasticsearchTemplateGeoTests { //given loadAnnotationBaseEntities(); CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery( - new Criteria("additionalLocation").within(new GeoPoint(51.001000, 0.10100), "1km")); + new Criteria("locationAsArray").within(new GeoPoint(51.001000, 0.10100), "1km")); //when - List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class); + List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class); //then assertThat(geoAuthorsForGeoCriteria.size(), is(3)); @@ -148,9 +167,9 @@ public class ElasticsearchTemplateGeoTests { //given loadAnnotationBaseEntities(); CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery( - new Criteria("additionalLocation").within("51.001000, 0.10100", "1km")); + new Criteria("locationAsArray").within("51.001000, 0.10100", "1km")); //when - List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class); + List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class); //then assertThat(geoAuthorsForGeoCriteria.size(), is(3)); @@ -161,9 +180,9 @@ public class ElasticsearchTemplateGeoTests { //given loadAnnotationBaseEntities(); CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery( - new Criteria("additionalLocation").within("u1044", "1km")); + new Criteria("locationAsArray").within("u1044", "1km")); //when - List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class); + List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, LocationMarkerEntity.class); //then assertThat(geoAuthorsForGeoCriteria.size(), is(3)); @@ -173,9 +192,9 @@ public class ElasticsearchTemplateGeoTests { public void shouldFindAllMarkersForNativeSearchQuery() { //Given loadAnnotationBaseEntities(); - NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoBoundingBoxFilter("additionalLocation").topLeft(52, -1).bottomRight(50, 1)); + NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoBoundingBoxFilter("locationAsArray").topLeft(52, -1).bottomRight(50, 1)); //When - List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(queryBuilder.build(), AuthorMarkerAnnotatedEntity.class); + List geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(queryBuilder.build(), LocationMarkerEntity.class); //Then assertThat(geoAuthorsForGeoCriteria.size(), is(3)); } @@ -228,4 +247,45 @@ public class ElasticsearchTemplateGeoTests { assertThat(geoAuthorsForGeoCriteria3.size(), is(2)); assertThat(geoAuthorsForGeoCriteria3, containsInAnyOrder(hasProperty("name", equalTo("Mohsin Husen")), hasProperty("name", equalTo("Rizwan Idrees")))); } + + @Test + public void shouldFindLocationWithGeoHashPrefix() { + + //given + //u1044k2bd6u - with precision = 4 -> u, u1, u10, u104 + //u1044k2bd6u - with precision = 5 -> u, u1, u10, u104, u1044 + + loadAnnotationBaseEntities(); + NativeSearchQueryBuilder locationWithPrefixAsDistancePrecision3 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsDistance").geohash("u1044k2bd6u").precision(3)); + NativeSearchQueryBuilder locationWithPrefixAsDistancePrecision4 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsDistance").geohash("u1044k2bd6u").precision(4)); + NativeSearchQueryBuilder locationWithPrefixAsDistancePrecision5 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsDistance").geohash("u1044k2bd6u").precision(5)); + + NativeSearchQueryBuilder locationWithPrefixAsLengthOfGeoHashPrecision4 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsLengthOfGeoHash").geohash("u1044k2bd6u").precision(4)); + NativeSearchQueryBuilder locationWithPrefixAsLengthOfGeoHashPrecision5 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsLengthOfGeoHash").geohash("u1044k2bd6u").precision(5)); + NativeSearchQueryBuilder locationWithPrefixAsLengthOfGeoHashPrecision6 = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoHashCellFilter("box-one").field("locationWithPrefixAsLengthOfGeoHash").geohash("u1044k2bd6u").precision(6)); + //when + List resultDistancePrecision3 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision3.build(), LocationMarkerEntity.class); + List resultDistancePrecision4 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision4.build(), LocationMarkerEntity.class); + List resultDistancePrecision5 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision5.build(), LocationMarkerEntity.class); + + List resultGeoHashLengthPrecision4 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision4.build(), LocationMarkerEntity.class); + List resultGeoHashLengthPrecision5 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision5.build(), LocationMarkerEntity.class); + List resultGeoHashLengthPrecision6 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision6.build(), LocationMarkerEntity.class); + + //then + assertThat(resultDistancePrecision3.size(), is(1)); + assertThat(resultDistancePrecision4.size(), is(1)); + assertThat(resultDistancePrecision5.size(), is(0)); + + assertThat(resultGeoHashLengthPrecision4.size(), is(2)); + assertThat(resultGeoHashLengthPrecision5.size(), is(2)); + assertThat(resultGeoHashLengthPrecision6.size(), is(0)); + } + + private IndexQuery buildIndex(LocationMarkerEntity result) { + IndexQuery indexQuery = new IndexQuery(); + indexQuery.setId(result.getId()); + indexQuery.setObject(result); + return indexQuery; + } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntity.java b/src/test/java/org/springframework/data/elasticsearch/core/geo/LocationMarkerEntity.java similarity index 60% rename from src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntity.java rename to src/test/java/org/springframework/data/elasticsearch/core/geo/LocationMarkerEntity.java index 640963254..03bf999c6 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/geo/AuthorMarkerAnnotatedEntity.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/geo/LocationMarkerEntity.java @@ -15,6 +15,7 @@ */ package org.springframework.data.elasticsearch.core.geo; +import lombok.*; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.GeoPointField; @@ -22,56 +23,27 @@ import org.springframework.data.elasticsearch.annotations.GeoPointField; /** * @author Franck Marchand */ +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder @Document(indexName = "test-geo-index", type = "geo-annotation-point-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1") -public class AuthorMarkerAnnotatedEntity { +public class LocationMarkerEntity { @Id private String id; private String name; @GeoPointField - private String location; + private String locationAsString; @GeoPointField - private double[] additionalLocation; + private double[] locationAsArray; - private AuthorMarkerAnnotatedEntity() { + @GeoPointField(geoHashPrefix = true, geoHashPrecision = "100km") + private String locationWithPrefixAsDistance; - } - - public AuthorMarkerAnnotatedEntity(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; - } - - public double[] getAdditionalLocation() { - return additionalLocation; - } - - public void setAdditionalLocation(double... additionalLocation) { - this.additionalLocation = additionalLocation; - } + @GeoPointField(geoHashPrefix = true, geoHashPrecision = "5") + private String locationWithPrefixAsLengthOfGeoHash; }