DATAES-172 - added test to cover geohash prefix

This commit is contained in:
Artur Konczak 2015-09-18 16:16:46 +01:00
parent 6a06bbfbb9
commit 5a648bcb7a
4 changed files with 101 additions and 149 deletions

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
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<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
List<LocationMarkerEntity> 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<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
List<LocationMarkerEntity> 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<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
List<LocationMarkerEntity> 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<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
List<LocationMarkerEntity> 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<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(queryBuilder.build(), AuthorMarkerAnnotatedEntity.class);
List<LocationMarkerEntity> 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<LocationMarkerEntity> resultDistancePrecision3 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision3.build(), LocationMarkerEntity.class);
List<LocationMarkerEntity> resultDistancePrecision4 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision4.build(), LocationMarkerEntity.class);
List<LocationMarkerEntity> resultDistancePrecision5 = elasticsearchTemplate.queryForList(locationWithPrefixAsDistancePrecision5.build(), LocationMarkerEntity.class);
List<LocationMarkerEntity> resultGeoHashLengthPrecision4 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision4.build(), LocationMarkerEntity.class);
List<LocationMarkerEntity> resultGeoHashLengthPrecision5 = elasticsearchTemplate.queryForList(locationWithPrefixAsLengthOfGeoHashPrecision5.build(), LocationMarkerEntity.class);
List<LocationMarkerEntity> 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;
}
}

View File

@ -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;
}