mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-14 08:02:11 +00:00
DATAES-172 - added test to cover geohash prefix
This commit is contained in:
parent
6a06bbfbb9
commit
5a648bcb7a
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user