DATAES-12 added support for GeoPoint

This commit is contained in:
Artur Konczak 2013-06-24 12:55:52 +01:00
parent 74a4035408
commit 5a499315e8
19 changed files with 1038 additions and 622 deletions

View File

@ -5,7 +5,7 @@
* 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
* 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,
@ -13,19 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core.geo;
package org.springframework.data.elasticsearch.annotations;
import java.util.List;
import java.lang.annotation.*;
/**
* Geo polygon used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
*
* @author Franck Marchand
* @author Artur Konczak
*/
public class GeoPolygon {
private List<GeoLocation> points;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface GeoPointField {
public GeoPolygon(List<GeoLocation> points) {
this.points = points;
}
}

View File

@ -16,8 +16,8 @@
package org.springframework.data.elasticsearch.core;
import org.elasticsearch.index.query.*;
import org.springframework.data.elasticsearch.core.geo.GeoBBox;
import org.springframework.data.elasticsearch.core.geo.GeoLocation;
import org.springframework.data.elasticsearch.core.geo.GeoEnvelope;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.util.Assert;
@ -46,25 +46,25 @@ class CriteriaFilterProcessor {
while (chainIterator.hasNext()) {
FilterBuilder fb = null;
Criteria chainedCriteria = chainIterator.next();
if(chainedCriteria.isOr()){
fb = orFilter(createFilterFragmentForCriteria(chainedCriteria).toArray(new FilterBuilder[]{ }));
if (chainedCriteria.isOr()) {
fb = orFilter(createFilterFragmentForCriteria(chainedCriteria).toArray(new FilterBuilder[]{}));
fbList.add(fb);
}else if(chainedCriteria.isNegating()){
} else if (chainedCriteria.isNegating()) {
List<FilterBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
if(!negationFilters.isEmpty()) {
if (!negationFilters.isEmpty()) {
fbList.addAll(negationFilters);
}
}else {
} else {
fbList.addAll(createFilterFragmentForCriteria(chainedCriteria));
}
}
if(!fbList.isEmpty()) {
if(fbList.size() == 1) {
filter =fbList.get(0);
if (!fbList.isEmpty()) {
if (fbList.size() == 1) {
filter = fbList.get(0);
} else {
filter = andFilter(fbList.toArray(new FilterBuilder[]{ }));
filter = andFilter(fbList.toArray(new FilterBuilder[]{}));
}
}
@ -77,10 +77,10 @@ class CriteriaFilterProcessor {
List<FilterBuilder> filterList = new LinkedList<FilterBuilder>();
String fieldName = chainedCriteria.getField().getName();
Assert.notNull(fieldName,"Unknown field");
Assert.notNull(fieldName, "Unknown field");
FilterBuilder filter = null;
while (it.hasNext()){
while (it.hasNext()) {
Criteria.CriteriaEntry entry = it.next();
filter = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
filterList.add(filter);
@ -96,36 +96,53 @@ class CriteriaFilterProcessor {
}
FilterBuilder filter = null;
switch (key){
case WITHIN: {
switch (key) {
case WITHIN: {
filter = geoDistanceFilter(fieldName);
Assert.isTrue(value instanceof Object[], "Value of a geo distance filter should be an array of two values.");
Object[] valArray = (Object[]) value;
Assert.noNullElements(valArray, "Geo distance filter takes 2 not null elements array as parameter.");
Assert.isTrue(valArray.length == 2, "Geo distance filter takes a 2-elements array as parameter.");
Assert.isTrue(valArray[0] instanceof GeoLocation, "First element of a geo distance filter must be a GeoLocation");
Assert.isTrue(valArray[0] instanceof GeoPoint || valArray[0] instanceof String, "First element of a geo distance filter must be a GeoLocation or String");
Assert.isTrue(valArray[1] instanceof String, "Second element of a geo distance filter must be a String");
GeoLocation loc = (GeoLocation)valArray[0];
String dist = (String)valArray[1];
String dist = (String) valArray[1];
if (valArray[0] instanceof GeoPoint) {
GeoPoint loc = (GeoPoint) valArray[0];
((GeoDistanceFilterBuilder) filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist);
} else {
String loc = (String) valArray[0];
if (loc.contains(",")) {
String c[] = loc.split(",");
((GeoDistanceFilterBuilder) filter).lat(Double.parseDouble(c[0])).lon(Double.parseDouble(c[1])).distance(dist);
} else {
((GeoDistanceFilterBuilder) filter).geohash(loc).distance(dist);
}
}
((GeoDistanceFilterBuilder)filter).lat(loc.getLat()).lon(loc.getLon()).distance(dist);
break;
}
case BBOX: {
filter = geoBoundingBoxFilter(fieldName);
Assert.isTrue(value instanceof Object[], "Value of a geo distance filter should be an array of two values.");
Assert.isTrue(value instanceof Object[], "Value of a bbox filter should be an array of one or two values.");
Object[] valArray = (Object[]) value;
Assert.noNullElements(valArray, "Geo bbox filter takes a not null element array as parameter.");
Assert.isTrue(valArray.length == 1, "Geo distance filter takes a 1-elements array as parameter.");
Assert.isTrue(valArray[0] instanceof GeoBBox, "single-element of a geo bbox filter must be a GeoBBox");
GeoBBox geoBBox = (GeoBBox)valArray[0];
((GeoBoundingBoxFilterBuilder)filter).topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
((GeoBoundingBoxFilterBuilder)filter).bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
if (valArray.length == 1) {
//GeoEnvelop
oneParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray[0]);
} else if (valArray.length == 2) {
//2x GeoPoint
//2x String
twoParameterBBox((GeoBoundingBoxFilterBuilder) filter, valArray);
} else {
//error
Assert.isTrue(false, "Geo distance filter takes a 1-elements array(GeoEnvelop) or 2-elements array(GeoPoints or Strings(geohash)).");
}
break;
}
@ -134,12 +151,43 @@ class CriteriaFilterProcessor {
return filter;
}
private List<FilterBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it){
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
Assert.isTrue(value instanceof GeoEnvelope, "single-element of a geo bbox filter must be type of GeoEnvelop");
GeoEnvelope geoBBox = (GeoEnvelope) value;
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
}
private static boolean isType(Object[] array, Class clazz) {
for (Object o : array) {
if (!clazz.isInstance(o)) {
return false;
}
}
return true;
}
private void twoParameterBBox(GeoBoundingBoxFilterBuilder filter, Object[] values) {
Assert.isTrue(isType(values, GeoPoint.class) || isType(values, String.class), " both elements of geo bbox filter must be type of GeoPoint or String(geohash)");
if (values[0] instanceof GeoPoint) {
GeoPoint topLeft = (GeoPoint) values[0];
GeoPoint bottomRight = (GeoPoint) values[1];
filter.topLeft(topLeft.getLat(), topLeft.getLon());
filter.bottomRight(bottomRight.getLat(), bottomRight.getLon());
} else {
String topLeft = (String) values[0];
String bottomRight = (String) values[1];
filter.topLeft(topLeft);
filter.bottomRight(bottomRight);
}
}
private List<FilterBuilder> buildNegationFilter(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
List<FilterBuilder> notFilterList = new LinkedList<FilterBuilder>();
while (it.hasNext()){
while (it.hasNext()) {
Criteria.CriteriaEntry criteriaEntry = it.next();
FilterBuilder notFilter = notFilter(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
FilterBuilder notFilter = notFilter(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
notFilterList.add(notFilter);
}

View File

@ -133,6 +133,16 @@ public interface ElasticsearchOperations {
*/
<T> List<T> queryForList(StringQuery query, Class<T> clazz);
/**
* Execute the search query against elasticsearch and return result as {@link List}
*
* @param query
* @param clazz
* @param <T>
* @return
*/
<T> List<T> queryForList(SearchQuery query, Class<T> clazz);
/**
* Execute the query against elasticsearch and return ids
*

View File

@ -170,6 +170,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
return queryForPage(query, clazz).getContent();
}
@Override
public <T> List<T> queryForList(SearchQuery query, Class<T> clazz) {
return queryForPage(query, clazz).getContent();
}
@Override
public <T> List<String> queryForIds(SearchQuery query) {
SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields();

View File

@ -18,7 +18,7 @@ package org.springframework.data.elasticsearch.core;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.springframework.data.elasticsearch.annotations.*;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import org.springframework.data.elasticsearch.core.geo.GeoLocation;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
@ -48,6 +48,7 @@ class MappingBuilder {
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
public static final String TYPE_VALUE_STRING = "string";
public static final String TYPE_VALUE_OBJECT = "object";
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
@ -73,12 +74,14 @@ class MappingBuilder {
mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
}
if(field.getType() == GeoLocation.class) {
applyGeoLocationFieldMapping(xContentBuilder, field);
}
Field singleField = field.getAnnotation(Field.class);
MultiField multiField = field.getAnnotation(MultiField.class);
GeoPointField geoPoint = field.getAnnotation(GeoPointField.class);
if (field.getType() == GeoPoint.class || geoPoint != null) {
applyGeoPointFieldMapping(xContentBuilder, field);
}
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
applyDefaultIdFieldMapping(xContentBuilder, field);
} else if (multiField != null) {
@ -94,10 +97,10 @@ class MappingBuilder {
}
private static void applyGeoLocationFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException {
private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException {
xContentBuilder.startObject(field.getName());
xContentBuilder.field("type", "geo_point")
.endObject();
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT)
.endObject();
}
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)

View File

@ -15,35 +15,27 @@
*/
package org.springframework.data.elasticsearch.core.geo;
import java.util.List;
/**
* Geo bbox used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
*
* @author Franck Marchand
*/
public class GeoBBox {
private GeoLocation topLeft;
private GeoLocation bottomRight;
public class GeoEnvelope {
public GeoBBox(GeoLocation topLeft, GeoLocation bottomRight) {
private GeoPoint topLeft;
private GeoPoint bottomRight;
public GeoEnvelope(GeoPoint topLeft, GeoPoint bottomRight) {
this.topLeft = topLeft;
this.bottomRight = bottomRight;
}
public GeoLocation getTopLeft() {
public GeoPoint getTopLeft() {
return topLeft;
}
public void setTopLeft(GeoLocation topLeft) {
this.topLeft = topLeft;
}
public GeoLocation getBottomRight() {
public GeoPoint getBottomRight() {
return bottomRight;
}
public void setBottomRight(GeoLocation bottomRight) {
this.bottomRight = bottomRight;
}
}

View File

@ -20,24 +20,16 @@ package org.springframework.data.elasticsearch.core.geo;
*
* @author Franck Marchand
*/
public class GeoLocation {
public class GeoPoint {
private double lat;
private double lon;
public GeoLocation lat(double lat) {
setLat(lat);
return this;
private GeoPoint() {
//required by mapper to instantiate object
}
public GeoLocation lon(double lon) {
setLon(lon);
return this;
}
public GeoLocation() {
}
public GeoLocation(double latitude, double longitude) {
public GeoPoint(double latitude, double longitude) {
this.lat = latitude;
this.lon = longitude;
}
@ -46,15 +38,8 @@ public class GeoLocation {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
}

View File

@ -25,341 +25,341 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.elasticsearch.core.geo.GeoBBox;
import org.springframework.data.elasticsearch.core.geo.GeoLocation;
import org.springframework.data.elasticsearch.core.geo.GeoEnvelope;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.util.Assert;
/**
* Criteria is the central class when constructing queries. It follows more or less a fluent API style, which allows to
* easily chain together multiple criteria.
*
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
*/
public class Criteria {
public static final String WILDCARD = "*";
public static final String CRITERIA_VALUE_SEPERATOR = " ";
public static final String WILDCARD = "*";
public static final String CRITERIA_VALUE_SEPERATOR = " ";
private static final String OR_OPERATOR = " OR ";
private static final String AND_OPERATOR = " AND ";
private static final String OR_OPERATOR = " OR ";
private static final String AND_OPERATOR = " AND ";
private Field field;
private float boost = Float.NaN;
private boolean negating = false;
private Field field;
private float boost = Float.NaN;
private boolean negating = false;
private List<Criteria> criteriaChain = new ArrayList<Criteria>(1);
private List<Criteria> criteriaChain = new ArrayList<Criteria>(1);
private Set<CriteriaEntry> queryCriteria = new LinkedHashSet<CriteriaEntry>();
private Set<CriteriaEntry> queryCriteria = new LinkedHashSet<CriteriaEntry>();
private Set<CriteriaEntry> filterCriteria = new LinkedHashSet<CriteriaEntry>();
public Criteria() {
}
public Criteria() {
}
/**
* Creates a new CriterSimpleFieldia for the Filed with provided name
*
* @param fieldname
*/
public Criteria(String fieldname) {
this(new SimpleField(fieldname));
}
/**
* Creates a new CriterSimpleFieldia for the Filed with provided name
*
* @param fieldname
*/
public Criteria(String fieldname) {
this(new SimpleField(fieldname));
}
/**
* Creates a new Criteria for the given field
*
* @param field
*/
public Criteria(Field field) {
Assert.notNull(field, "Field for criteria must not be null");
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
/**
* Creates a new Criteria for the given field
*
* @param field
*/
public Criteria(Field field) {
Assert.notNull(field, "Field for criteria must not be null");
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
this.criteriaChain.add(this);
this.field = field;
}
this.criteriaChain.add(this);
this.field = field;
}
protected Criteria(List<Criteria> criteriaChain, String fieldname) {
this(criteriaChain, new SimpleField(fieldname));
}
protected Criteria(List<Criteria> criteriaChain, String fieldname) {
this(criteriaChain, new SimpleField(fieldname));
}
protected Criteria(List<Criteria> criteriaChain, Field field) {
Assert.notNull(criteriaChain, "CriteriaChain must not be null");
Assert.notNull(field, "Field for criteria must not be null");
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
protected Criteria(List<Criteria> criteriaChain, Field field) {
Assert.notNull(criteriaChain, "CriteriaChain must not be null");
Assert.notNull(field, "Field for criteria must not be null");
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
this.criteriaChain.addAll(criteriaChain);
this.criteriaChain.add(this);
this.field = field;
}
this.criteriaChain.addAll(criteriaChain);
this.criteriaChain.add(this);
this.field = field;
}
/**
* Static factory method to create a new Criteria for field with given name
*
* @param field
* @return
*/
public static Criteria where(String field) {
return where(new SimpleField(field));
}
/**
* Static factory method to create a new Criteria for field with given name
*
* @param field
* @return
*/
public static Criteria where(String field) {
return where(new SimpleField(field));
}
/**
* Static factory method to create a new Criteria for provided field
*
* @param field
* @return
*/
public static Criteria where(Field field) {
return new Criteria(field);
}
/**
* Static factory method to create a new Criteria for provided field
*
* @param field
* @return
*/
public static Criteria where(Field field) {
return new Criteria(field);
}
/**
* Chain using {@code AND}
*
* @param field
* @return
*/
public Criteria and(Field field) {
return new Criteria(this.criteriaChain, field);
}
/**
* Chain using {@code AND}
*
* @param field
* @return
*/
public Criteria and(Field field) {
return new Criteria(this.criteriaChain, field);
}
/**
* Chain using {@code AND}
*
* @param fieldName
* @return
*/
public Criteria and(String fieldName) {
return new Criteria(this.criteriaChain, fieldName);
}
/**
* Chain using {@code AND}
*
* @param fieldName
* @return
*/
public Criteria and(String fieldName) {
return new Criteria(this.criteriaChain, fieldName);
}
/**
* Chain using {@code AND}
*
* @param criteria
* @return
*/
public Criteria and(Criteria criteria) {
this.criteriaChain.add(criteria);
return this;
}
/**
* Chain using {@code AND}
*
* @param criteria
* @return
*/
public Criteria and(Criteria criteria) {
this.criteriaChain.add(criteria);
return this;
}
/**
* Chain using {@code AND}
*
* @param criterias
* @return
*/
public Criteria and(Criteria... criterias) {
this.criteriaChain.addAll(Arrays.asList(criterias));
return this;
}
/**
* Chain using {@code AND}
*
* @param criterias
* @return
*/
public Criteria and(Criteria... criterias) {
this.criteriaChain.addAll(Arrays.asList(criterias));
return this;
}
/**
* Chain using {@code OR}
*
* @param field
* @return
*/
public Criteria or(Field field) {
return new OrCriteria(this.criteriaChain, field);
}
/**
* Chain using {@code OR}
*
* @param field
* @return
*/
public Criteria or(Field field) {
return new OrCriteria(this.criteriaChain, field);
}
/**
* Chain using {@code OR}
*
* @param criteria
* @return
*/
public Criteria or(Criteria criteria) {
Assert.notNull(criteria, "Cannot chain 'null' criteria.");
/**
* Chain using {@code OR}
*
* @param criteria
* @return
*/
public Criteria or(Criteria criteria) {
Assert.notNull(criteria, "Cannot chain 'null' criteria.");
Criteria orConnectedCritiera = new OrCriteria(this.criteriaChain, criteria.getField());
orConnectedCritiera.queryCriteria.addAll(criteria.queryCriteria);
return orConnectedCritiera;
}
Criteria orConnectedCritiera = new OrCriteria(this.criteriaChain, criteria.getField());
orConnectedCritiera.queryCriteria.addAll(criteria.queryCriteria);
return orConnectedCritiera;
}
/**
* Chain using {@code OR}
*
* @param fieldName
* @return
*/
public Criteria or(String fieldName) {
return or(new SimpleField(fieldName));
}
/**
* Chain using {@code OR}
*
* @param fieldName
* @return
*/
public Criteria or(String fieldName) {
return or(new SimpleField(fieldName));
}
/**
* Crates new CriteriaEntry without any wildcards
*
* @param o
* @return
*/
public Criteria is(Object o) {
queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o));
return this;
}
/**
* Crates new CriteriaEntry without any wildcards
*
* @param o
* @return
*/
public Criteria is(Object o) {
queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o));
return this;
}
/**
* Crates new CriteriaEntry with leading and trailing wildcards <br/>
* <strong>NOTE: </strong> mind your schema as leading wildcards may not be supported and/or execution might be slow.
*
* @param s
* @return
*/
public Criteria contains(String s) {
assertNoBlankInWildcardedQuery(s, true, true);
queryCriteria.add(new CriteriaEntry(OperationKey.CONTAINS, s));
return this;
}
/**
* Crates new CriteriaEntry with leading and trailing wildcards <br/>
* <strong>NOTE: </strong> mind your schema as leading wildcards may not be supported and/or execution might be slow.
*
* @param s
* @return
*/
public Criteria contains(String s) {
assertNoBlankInWildcardedQuery(s, true, true);
queryCriteria.add(new CriteriaEntry(OperationKey.CONTAINS, s));
return this;
}
/**
* Crates new CriteriaEntry with trailing wildcard
*
* @param s
* @return
*/
public Criteria startsWith(String s) {
assertNoBlankInWildcardedQuery(s, true, false);
queryCriteria.add(new CriteriaEntry(OperationKey.STARTS_WITH, s));
return this;
}
/**
* Crates new CriteriaEntry with trailing wildcard
*
* @param s
* @return
*/
public Criteria startsWith(String s) {
assertNoBlankInWildcardedQuery(s, true, false);
queryCriteria.add(new CriteriaEntry(OperationKey.STARTS_WITH, s));
return this;
}
/**
* Crates new CriteriaEntry with leading wildcard <br />
* <strong>NOTE: </strong> mind your schema and execution times as leading wildcards may not be supported.
*
* @param s
* @return
*/
public Criteria endsWith(String s) {
assertNoBlankInWildcardedQuery(s, false, true);
queryCriteria.add(new CriteriaEntry(OperationKey.ENDS_WITH, s));
return this;
}
/**
* Crates new CriteriaEntry with leading wildcard <br />
* <strong>NOTE: </strong> mind your schema and execution times as leading wildcards may not be supported.
*
* @param s
* @return
*/
public Criteria endsWith(String s) {
assertNoBlankInWildcardedQuery(s, false, true);
queryCriteria.add(new CriteriaEntry(OperationKey.ENDS_WITH, s));
return this;
}
/**
* Crates new CriteriaEntry with trailing -
*
* @return
*/
public Criteria not() {
this.negating = true;
return this;
}
/**
* Crates new CriteriaEntry with trailing -
*
* @return
*/
public Criteria not() {
this.negating = true;
return this;
}
/**
* Crates new CriteriaEntry with trailing ~
*
* @param s
* @return
*/
public Criteria fuzzy(String s) {
/**
* Crates new CriteriaEntry with trailing ~
*
* @param s
* @return
*/
public Criteria fuzzy(String s) {
queryCriteria.add(new CriteriaEntry(OperationKey.FUZZY, s));
return this;
}
}
/**
* Crates new CriteriaEntry allowing native elasticsearch expressions
*
* @param s
* @return
*/
public Criteria expression(String s) {
queryCriteria.add(new CriteriaEntry(OperationKey.EXPRESSION, s));
return this;
}
/**
* Crates new CriteriaEntry allowing native elasticsearch expressions
*
* @param s
* @return
*/
public Criteria expression(String s) {
queryCriteria.add(new CriteriaEntry(OperationKey.EXPRESSION, s));
return this;
}
/**
* Boost positive hit with given factor. eg. ^2.3
*
* @param boost
* @return
*/
public Criteria boost(float boost) {
if (boost < 0) {
throw new InvalidDataAccessApiUsageException("Boost must not be negative.");
}
this.boost = boost;
return this;
}
/**
* Boost positive hit with given factor. eg. ^2.3
*
* @param boost
* @return
*/
public Criteria boost(float boost) {
if (boost < 0) {
throw new InvalidDataAccessApiUsageException("Boost must not be negative.");
}
this.boost = boost;
return this;
}
/**
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO upperBound]}
*
* @param lowerBound
* @param upperBound
* @return
*/
public Criteria between(Object lowerBound, Object upperBound) {
if (lowerBound == null && upperBound == null) {
throw new InvalidDataAccessApiUsageException("Range [* TO *] is not allowed");
}
/**
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO upperBound]}
*
* @param lowerBound
* @param upperBound
* @return
*/
public Criteria between(Object lowerBound, Object upperBound) {
if (lowerBound == null && upperBound == null) {
throw new InvalidDataAccessApiUsageException("Range [* TO *] is not allowed");
}
queryCriteria.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[]{lowerBound, upperBound}));
return this;
}
queryCriteria.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[]{lowerBound, upperBound}));
return this;
}
/**
* Crates new CriteriaEntry for {@code RANGE [* TO upperBound]}
*
* @param upperBound
* @return
*/
public Criteria lessThanEqual(Object upperBound) {
between(null, upperBound);
return this;
}
/**
* Crates new CriteriaEntry for {@code RANGE [* TO upperBound]}
*
* @param upperBound
* @return
*/
public Criteria lessThanEqual(Object upperBound) {
between(null, upperBound);
return this;
}
/**
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO *]}
*
* @param lowerBound
* @return
*/
public Criteria greaterThanEqual(Object lowerBound) {
between(lowerBound, null);
return this;
}
/**
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO *]}
*
* @param lowerBound
* @return
*/
public Criteria greaterThanEqual(Object lowerBound) {
between(lowerBound, null);
return this;
}
/**
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
*
* @param values
* @return
*/
public Criteria in(Object... values) {
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
throw new InvalidDataAccessApiUsageException("At least one element "
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
+ " has to be present.");
}
return in(Arrays.asList(values));
}
/**
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
*
* @param values
* @return
*/
public Criteria in(Object... values) {
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
throw new InvalidDataAccessApiUsageException("At least one element "
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
+ " has to be present.");
}
return in(Arrays.asList(values));
}
/**
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
*
* @param values the collection containing the values to match against
* @return
*/
public Criteria in(Iterable<?> values) {
Assert.notNull(values, "Collection of 'in' values must not be null");
/**
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
*
* @param values the collection containing the values to match against
* @return
*/
public Criteria in(Iterable<?> values) {
Assert.notNull(values, "Collection of 'in' values must not be null");
queryCriteria.add(new CriteriaEntry(OperationKey.IN, values));
return this;
}
/**
* Creates new CriteriaEntry for {@code location WITHIN distance}
* @param location {@link GeoLocation} center coordinates
* @param distance {@link String} radius as a string (e.g. : '100km').
* Distance unit :
* either mi/miles or km can be set
*
* @param location {@link org.springframework.data.elasticsearch.core.geo.GeoPoint} center coordinates
* @param distance {@link String} radius as a string (e.g. : '100km').
* Distance unit :
* either mi/miles or km can be set
* @return Criteria the chaind criteria with the new 'within' criteria included.
*/
public Criteria within(GeoLocation location, String distance) {
public Criteria within(GeoPoint location, String distance) {
Assert.notNull(location, "Location value for near criteria must not be null");
Assert.notNull(location, "Distance value for near criteria must not be null");
filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{location, distance}));
@ -367,125 +367,172 @@ public class Criteria {
}
/**
* Creates new CriteriaEntry for {@code location BBOX bounding box}
* @param bbox {@link org.springframework.data.elasticsearch.core.geo.GeoBBox} center coordinates
* Creates new CriteriaEntry for {@code geoLocation WITHIN distance}
*
* @param geoLocation {@link String} center point
* supported formats:
* lat on = > "41.2,45.1",
* geohash = > "asd9as0d"
* @param distance {@link String} radius as a string (e.g. : '100km').
* Distance unit :
* either mi/miles or km can be set
* @return
*/
public Criteria within(String geoLocation, String distance) {
Assert.isTrue(StringUtils.isNotBlank(geoLocation), "geoLocation value must not be null");
filterCriteria.add(new CriteriaEntry(OperationKey.WITHIN, new Object[]{geoLocation, distance}));
return this;
}
/**
* Creates new CriteriaEntry for {@code location BBOX bounding box}
*
* @param bbox {@link org.springframework.data.elasticsearch.core.geo.GeoEnvelope} bounding box(left top corner + right bottom corner)
* @return Criteria the chaind criteria with the new 'bbox' criteria included.
*/
public Criteria bbox(GeoBBox bbox) {
public Criteria bbox(GeoEnvelope bbox) {
Assert.notNull(bbox, "bbox value for bbox criteria must not be null");
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{bbox}));
return this;
}
}
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use epxression or mulitple clauses instead.");
}
}
/**
* Field targeted by this Criteria
*
* @return
*/
public Field getField() {
return this.field;
}
/**
* Creates new CriteriaEntry for bounding box created from points
*
* @param topLeft left top corner of bounding box
* @param bottomRight right bottom corner of bounding box
* @return Criteria the chaind criteria with the new 'bbox' criteria included.
*/
public Criteria bbox(String topLeft, String bottomRight) {
Assert.isTrue(StringUtils.isNotBlank(topLeft), "topLeft point must not be empty");
Assert.isTrue(StringUtils.isNotBlank(bottomRight), "bottomRight point must not be empty");
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeft, bottomRight}));
return this;
}
public Set<CriteriaEntry> getQueryCriteriaEntries() {
return Collections.unmodifiableSet(this.queryCriteria);
}
/**
* Creates new CriteriaEntry for bounding box created from points
*
* @param topLeft left top corner of bounding box
* @param bottomRight right bottom corner of bounding box
* @return Criteria the chaind criteria with the new 'bbox' criteria included.
*/
public Criteria bbox(GeoPoint topLeft, GeoPoint bottomRight) {
Assert.notNull(topLeft, "topLeft point must not be null");
Assert.notNull(bottomRight, "bottomRight point must not be null");
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{topLeft, bottomRight}));
return this;
}
public Set<CriteriaEntry> getFilterCriteriaEntries() {
return Collections.unmodifiableSet(this.filterCriteria);
}
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use epxression or mulitple clauses instead.");
}
}
/**
* Field targeted by this Criteria
*
* @return
*/
public Field getField() {
return this.field;
}
public Set<CriteriaEntry> getQueryCriteriaEntries() {
return Collections.unmodifiableSet(this.queryCriteria);
}
public Set<CriteriaEntry> getFilterCriteriaEntries() {
return Collections.unmodifiableSet(this.filterCriteria);
}
public Set<CriteriaEntry> getFilterCriteria() {
return filterCriteria;
}
/**
* Conjunction to be used with this criteria (AND | OR)
*
* @return
*/
public String getConjunctionOperator() {
return AND_OPERATOR;
}
/**
* Conjunction to be used with this criteria (AND | OR)
*
* @return
*/
public String getConjunctionOperator() {
return AND_OPERATOR;
}
public List<Criteria> getCriteriaChain() {
return Collections.unmodifiableList(this.criteriaChain);
}
public List<Criteria> getCriteriaChain() {
return Collections.unmodifiableList(this.criteriaChain);
}
public boolean isNegating() {
return this.negating;
}
public boolean isNegating() {
return this.negating;
}
public boolean isAnd() {
return AND_OPERATOR == getConjunctionOperator();
}
public boolean isAnd() {
return AND_OPERATOR == getConjunctionOperator();
}
public boolean isOr() {
return OR_OPERATOR == getConjunctionOperator();
}
public boolean isOr() {
return OR_OPERATOR == getConjunctionOperator();
}
public float getBoost() {
return this.boost;
}
public float getBoost() {
return this.boost;
}
static class OrCriteria extends Criteria {
static class OrCriteria extends Criteria {
public OrCriteria() {
super();
}
public OrCriteria() {
super();
}
public OrCriteria(Field field) {
super(field);
}
public OrCriteria(Field field) {
super(field);
}
public OrCriteria(List<Criteria> criteriaChain, Field field) {
super(criteriaChain, field);
}
public OrCriteria(List<Criteria> criteriaChain, Field field) {
super(criteriaChain, field);
}
public OrCriteria(List<Criteria> criteriaChain, String fieldname) {
super(criteriaChain, fieldname);
}
public OrCriteria(List<Criteria> criteriaChain, String fieldname) {
super(criteriaChain, fieldname);
}
public OrCriteria(String fieldname) {
super(fieldname);
}
public OrCriteria(String fieldname) {
super(fieldname);
}
@Override
public String getConjunctionOperator() {
return OR_OPERATOR;
}
@Override
public String getConjunctionOperator() {
return OR_OPERATOR;
}
}
}
public enum OperationKey {
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, WITHIN, BBOX, NEAR;
}
public enum OperationKey {
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, WITHIN, BBOX, NEAR;
}
public static class CriteriaEntry {
public static class CriteriaEntry {
private OperationKey key;
private Object value;
private OperationKey key;
private Object value;
CriteriaEntry(OperationKey key, Object value) {
this.key = key;
this.value = value;
}
CriteriaEntry(OperationKey key, Object value) {
this.key = key;
this.value = value;
}
public OperationKey getKey() {
return key;
}
public OperationKey getKey() {
return key;
}
public Object getValue() {
return value;
}
public Object getValue() {
return value;
}
}
}
}

View File

@ -1,47 +0,0 @@
package org.springframework.data.elasticsearch;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
/**
* Simple type to test facets
*/
public class ArticleBuilder {
private Article resutl;
public ArticleBuilder(String id) {
resutl = new Article(id);
}
public ArticleBuilder title(String title) {
resutl.setTitle(title);
return this;
}
public ArticleBuilder addAuthor(String author) {
resutl.getAuthors().add(author);
return this;
}
public ArticleBuilder addPublishedYear(Integer year) {
resutl.getPublishedYears().add(year);
return this;
}
public ArticleBuilder score(int score) {
resutl.setScore(score);
return this;
}
public Article build() {
return resutl;
}
public IndexQuery buildIndex() {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(resutl.getId());
indexQuery.setObject(resutl);
return indexQuery;
}
}

View File

@ -27,11 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.GeoAuthor;
import org.springframework.data.elasticsearch.SampleEntity;
import org.springframework.data.elasticsearch.SampleMappingEntity;
import org.springframework.data.elasticsearch.core.geo.GeoBBox;
import org.springframework.data.elasticsearch.core.geo.GeoLocation;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ -46,7 +43,8 @@ import static org.elasticsearch.index.query.QueryBuilders.fieldQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Rizwan Idrees
@ -65,12 +63,6 @@ public class ElasticsearchTemplateTests {
elasticsearchTemplate.deleteIndex(SampleEntity.class);
elasticsearchTemplate.createIndex(SampleEntity.class);
elasticsearchTemplate.refresh(SampleEntity.class, true);
elasticsearchTemplate.deleteIndex(GeoAuthor.class);
elasticsearchTemplate.createIndex(GeoAuthor.class);
elasticsearchTemplate.refresh(GeoAuthor.class, true);
elasticsearchTemplate.putMapping(GeoAuthor.class);
}
@Test
@ -725,86 +717,4 @@ public class ElasticsearchTemplateTests {
// then
assertThat(elasticsearchTemplate.indexExists(clazz), is(false));
}
@Test
public void shouldPutMappingForGivenEntityWithGeoLocation()throws Exception{
//given
Class entity = GeoAuthor.class;
elasticsearchTemplate.createIndex(entity);
//when
assertThat(elasticsearchTemplate.putMapping(entity) , is(true)) ;
}
@Test
public void shouldReturnListForGivenCriteriaWithGeoLocation(){
//given
List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
//first document
String documentId = randomNumeric(5);
GeoAuthor geoAuthor1 = new GeoAuthor();
geoAuthor1.setId(documentId);
geoAuthor1.setName("Franck Marchand");
geoAuthor1.setLocation(new GeoLocation(45.7806d, 3.0875d)); // Clermont-Ferrand
IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(documentId);
indexQuery1.setObject(geoAuthor1);
indexQueries.add(indexQuery1);
//second document
String documentId2 = randomNumeric(5);
GeoAuthor geoAuthor2 = new GeoAuthor();
geoAuthor2.setId(documentId2);
geoAuthor2.setName("Mohsin Husen");
geoAuthor2.setLocation(new GeoLocation(51.5171d, 0.1062d)); // London
IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(documentId2);
indexQuery2.setObject(geoAuthor2);
indexQueries.add(indexQuery2);
//third document
String documentId3 = randomNumeric(5);
GeoAuthor geoAuthor3 = new GeoAuthor();
geoAuthor3.setId(documentId3);
geoAuthor3.setName("Rizwan Idrees");
geoAuthor3.setLocation(new GeoLocation(51.5171d, 0.1062d)); // London
IndexQuery indexQuery3 = new IndexQuery();
indexQuery3.setId(documentId3);
indexQuery3.setObject(geoAuthor3);
indexQueries.add(indexQuery3);
//when
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(GeoAuthor.class, true);
//when
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
new Criteria("location").within(new GeoLocation(45.7806d, 3.0875d), "20km"));
List<GeoAuthor> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery,GeoAuthor.class);
//then
assertThat(geoAuthorsForGeoCriteria.size(),is(1));
assertEquals("Franck Marchand", geoAuthorsForGeoCriteria.get(0).getName());
// query/filter geo distance mixed query
CriteriaQuery geoLocationCriteriaQuery2 = new CriteriaQuery(
new Criteria("name").is("Mohsin Husen").and("location").within(new GeoLocation(51.5171d, 0.1062d), "20km"));
List<GeoAuthor> geoAuthorsForGeoCriteria2 = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery2,GeoAuthor.class);
assertThat(geoAuthorsForGeoCriteria2.size(),is(1));
assertEquals("Mohsin Husen", geoAuthorsForGeoCriteria2.get(0).getName());
// bbox query
CriteriaQuery geoLocationCriteriaQuery3 = new CriteriaQuery(
new Criteria("location").bbox(
new GeoBBox(new GeoLocation(53.5171d, 0),
new GeoLocation(49.5171d, 0.2062d))));
List<GeoAuthor> geoAuthorsForGeoCriteria3 = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery3,GeoAuthor.class);
assertThat(geoAuthorsForGeoCriteria3.size(),is(2));
assertThat(geoAuthorsForGeoCriteria3, containsInAnyOrder(hasProperty("name", equalTo("Mohsin Husen")), hasProperty("name",equalTo("Rizwan Idrees"))));
}
}

View File

@ -1,4 +1,4 @@
package org.springframework.data.elasticsearch;
package org.springframework.data.elasticsearch.core.facet;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.*;
@ -15,7 +15,7 @@ import static org.springframework.data.elasticsearch.annotations.FieldType.Strin
* Simple type to test facets
*/
@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1")
public class Article {
public class ArticleEntity {
@Id
private String id;
@ -36,11 +36,11 @@ public class Article {
private int score;
public Article() {
private ArticleEntity(){
}
public Article(String id) {
public ArticleEntity(String id) {
this.id = id;
}

View File

@ -0,0 +1,47 @@
package org.springframework.data.elasticsearch.core.facet;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
/**
* Simple type to test facets
*/
public class ArticleEntityBuilder {
private ArticleEntity result;
public ArticleEntityBuilder(String id) {
result = new ArticleEntity(id);
}
public ArticleEntityBuilder title(String title) {
result.setTitle(title);
return this;
}
public ArticleEntityBuilder addAuthor(String author) {
result.getAuthors().add(author);
return this;
}
public ArticleEntityBuilder addPublishedYear(Integer year) {
result.getPublishedYears().add(year);
return this;
}
public ArticleEntityBuilder score(int score) {
result.setScore(score);
return this;
}
public ArticleEntity build() {
return result;
}
public IndexQuery buildIndex() {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(result.getId());
indexQuery.setObject(result);
return indexQuery;
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
package org.springframework.data.elasticsearch.core.facet;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.search.facet.FacetBuilders;
@ -21,8 +21,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.Article;
import org.springframework.data.elasticsearch.ArticleBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.FacetedPage;
import org.springframework.data.elasticsearch.core.facet.request.NativeFacetRequest;
import org.springframework.data.elasticsearch.core.facet.request.RangeFacetRequestBuilder;
import org.springframework.data.elasticsearch.core.facet.request.TermFacetRequestBuilder;
@ -62,21 +62,21 @@ public class ElasticsearchTemplateFacetTests {
@Before
public void before() {
elasticsearchTemplate.deleteIndex(Article.class);
elasticsearchTemplate.createIndex(Article.class);
elasticsearchTemplate.putMapping(Article.class);
elasticsearchTemplate.refresh(Article.class, true);
elasticsearchTemplate.deleteIndex(ArticleEntity.class);
elasticsearchTemplate.createIndex(ArticleEntity.class);
elasticsearchTemplate.putMapping(ArticleEntity.class);
elasticsearchTemplate.refresh(ArticleEntity.class, true);
IndexQuery article1 = new ArticleBuilder("1").title("article four").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addAuthor(JONATHAN_YAN).score(10).buildIndex();
IndexQuery article2 = new ArticleBuilder("2").title("article three").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addPublishedYear(YEAR_2000).score(20).buildIndex();
IndexQuery article3 = new ArticleBuilder("3").title("article two").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(30).buildIndex();
IndexQuery article4 = new ArticleBuilder("4").title("article one").addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(40).buildIndex();
IndexQuery article1 = new ArticleEntityBuilder("1").title("article four").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addAuthor(JONATHAN_YAN).score(10).buildIndex();
IndexQuery article2 = new ArticleEntityBuilder("2").title("article three").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addPublishedYear(YEAR_2000).score(20).buildIndex();
IndexQuery article3 = new ArticleEntityBuilder("3").title("article two").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(30).buildIndex();
IndexQuery article4 = new ArticleEntityBuilder("4").title("article one").addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(40).buildIndex();
elasticsearchTemplate.index(article1);
elasticsearchTemplate.index(article2);
elasticsearchTemplate.index(article3);
elasticsearchTemplate.index(article4);
elasticsearchTemplate.refresh(Article.class, true);
elasticsearchTemplate.refresh(ArticleEntity.class, true);
}
@Test
@ -86,7 +86,7 @@ public class ElasticsearchTemplateFacetTests {
String facetName = "fauthors";
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -117,7 +117,7 @@ public class ElasticsearchTemplateFacetTests {
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(3)));
@ -143,7 +143,7 @@ public class ElasticsearchTemplateFacetTests {
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").excludeTerms(RIZWAN_IDREES, ARTUR_KONCZAK).build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(3)));
@ -165,7 +165,7 @@ public class ElasticsearchTemplateFacetTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").ascTerm().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -196,7 +196,7 @@ public class ElasticsearchTemplateFacetTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").ascCount().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -226,7 +226,7 @@ public class ElasticsearchTemplateFacetTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).fields("publishedYears").descCount().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -256,7 +256,7 @@ public class ElasticsearchTemplateFacetTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new TermFacetRequestBuilder(facetName).fields("publishedYears", "authors.untouched").ascTerm().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -305,7 +305,7 @@ public class ElasticsearchTemplateFacetTests {
.withFacet(new TermFacetRequestBuilder(stringFacetName).fields("authors.untouched").ascTerm().build())
.build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -352,7 +352,7 @@ public class ElasticsearchTemplateFacetTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withFacet(new NativeFacetRequest(FacetBuilders.termsFacet(facetName).field("publishedYears"))).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -381,7 +381,7 @@ public class ElasticsearchTemplateFacetTests {
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").regex("Art.*").build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(3)));
@ -403,7 +403,7 @@ public class ElasticsearchTemplateFacetTests {
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").allTerms().build()).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(3)));
@ -423,7 +423,7 @@ public class ElasticsearchTemplateFacetTests {
.to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build()
).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));
@ -460,7 +460,7 @@ public class ElasticsearchTemplateFacetTests {
.to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build()
).build();
// when
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
// then
assertThat(result.getNumberOfElements(), is(equalTo(4)));

View File

@ -0,0 +1,77 @@
/*
* 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.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
/**
* @author Franck Marchand
*/
@Document(indexName = "test-geo-index", type = "geo-annotation-point-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
public class AuthorMarkerAnnotatedEntity {
@Id
private String id;
private String name;
@GeoPointField
private String location;
@GeoPointField
private double[] additionalLocation;
private AuthorMarkerAnnotatedEntity() {
}
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;
}
}

View File

@ -0,0 +1,53 @@
/*
* 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;
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

@ -13,23 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch;
package org.springframework.data.elasticsearch.core.geo;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.geo.GeoLocation;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
/**
* @author Franck Marchand
*/
@Document(indexName = "test-geo-index", type = "test-geo-type")
public class GeoAuthor {
@Document(indexName = "test-geo-index", type = "geo-class-point-type", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
public class AuthorMarkerEntity {
@Id
private String id;
private String name;
private GeoLocation location;
private GeoPoint location;
private AuthorMarkerEntity(){
}
public AuthorMarkerEntity(String id){
this.id = id;
}
public String getId() {
return id;
@ -47,11 +54,11 @@ public class GeoAuthor {
this.name = name;
}
public GeoLocation getLocation() {
public GeoPoint getLocation() {
return location;
}
public void setLocation(GeoLocation location) {
public void setLocation(GeoPoint location) {
this.location = location;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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;
public class AuthorMarkerEntityBuilder {
private AuthorMarkerEntity result;
public AuthorMarkerEntityBuilder(String id) {
result = new AuthorMarkerEntity(id);
}
public AuthorMarkerEntityBuilder name(String name) {
result.setName(name);
return this;
}
public AuthorMarkerEntityBuilder location(double latitude, double longitude) {
result.setLocation(new GeoPoint(latitude, longitude));
return this;
}
public AuthorMarkerEntity build() {
return result;
}
public IndexQuery buildIndex() {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(result.getId());
indexQuery.setObject(result);
return indexQuery;
}
}

View File

@ -0,0 +1,236 @@
/*
* 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.elasticsearch.index.query.FilterBuilders;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Franck Marchand
* @author Artur Konczak
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
public class ElasticsearchTemplateGeoTests {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Before
public void before() {
}
private void loadClassBaseEntities() {
elasticsearchTemplate.deleteIndex(AuthorMarkerEntity.class);
elasticsearchTemplate.createIndex(AuthorMarkerEntity.class);
elasticsearchTemplate.refresh(AuthorMarkerEntity.class, true);
elasticsearchTemplate.putMapping(AuthorMarkerEntity.class);
List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
indexQueries.add(new AuthorMarkerEntityBuilder("1").name("Franck Marchand").location(45.7806d, 3.0875d).buildIndex());
indexQueries.add(new AuthorMarkerEntityBuilder("2").name("Mohsin Husen").location(51.5171d, 0.1062d).buildIndex());
indexQueries.add(new AuthorMarkerEntityBuilder("3").name("Rizwan Idrees").location(51.5171d, 0.1062d).buildIndex());
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(AuthorMarkerEntity.class, true);
}
private void loadAnnotationBaseEntities() {
elasticsearchTemplate.deleteIndex(AuthorMarkerAnnotatedEntity.class);
elasticsearchTemplate.createIndex(AuthorMarkerAnnotatedEntity.class);
elasticsearchTemplate.refresh(AuthorMarkerAnnotatedEntity.class, true);
elasticsearchTemplate.putMapping(AuthorMarkerAnnotatedEntity.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(3)).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());
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(AuthorMarkerEntity.class, true);
}
@Test
public void shouldPutMappingForGivenEntityWithGeoLocation() throws Exception {
//given
Class entity = AuthorMarkerEntity.class;
elasticsearchTemplate.createIndex(entity);
//when
assertThat(elasticsearchTemplate.putMapping(entity), is(true));
}
@Test
public void shouldFindAuthorMarkersInRangeForGivenCriteriaQuery() {
//given
loadClassBaseEntities();
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
new Criteria("location").within(new GeoPoint(45.7806d, 3.0875d), "20km"));
//when
List<AuthorMarkerEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria.size(), is(1));
assertEquals("Franck Marchand", geoAuthorsForGeoCriteria.get(0).getName());
}
@Test
public void shouldFindSelectedAuthorMarkerInRangeForGivenCriteriaQuery() {
//given
loadClassBaseEntities();
CriteriaQuery geoLocationCriteriaQuery2 = new CriteriaQuery(
new Criteria("name").is("Mohsin Husen").and("location").within(new GeoPoint(51.5171d, 0.1062d), "20km"));
//when
List<AuthorMarkerEntity> geoAuthorsForGeoCriteria2 = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery2, AuthorMarkerEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria2.size(), is(1));
assertEquals("Mohsin Husen", geoAuthorsForGeoCriteria2.get(0).getName());
}
@Test
public void shouldFindStringAnnotatedGeoMarkersInRangeForGivenCriteriaQuery() {
//given
loadAnnotationBaseEntities();
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
new Criteria("location").within(new GeoPoint(51.000000, 0.100000), "1km"));
//when
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria.size(), is(1));
//TODO: result should be 3 not 1 - geohash points don't work
assertEquals("Artur Konczak", geoAuthorsForGeoCriteria.get(0).getName());
}
@Test
public void shouldFindDoubleAnnotatedGeoMarkersInRangeForGivenCriteriaQuery() {
//given
loadAnnotationBaseEntities();
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
new Criteria("additionalLocation").within(new GeoPoint(51.001000, 0.10100), "1km"));
//when
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
}
@Test
public void shouldFindAnnotatedGeoMarkersInRangeForGivenCriteriaQuery() {
//given
loadAnnotationBaseEntities();
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
new Criteria("additionalLocation").within("51.001000, 0.10100", "1km"));
//when
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
}
@Test
public void shouldFindAnnotatedGeoMarkersInRangeForGivenCriteriaQueryUsingGeohashLocation() {
//given
loadAnnotationBaseEntities();
CriteriaQuery geoLocationCriteriaQuery = new CriteriaQuery(
new Criteria("additionalLocation").within("u1044", "1km"));
//when
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery, AuthorMarkerAnnotatedEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
}
@Test
public void shouldFindAllMarkersForNativeSearchQuery() {
//Given
loadAnnotationBaseEntities();
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder().withFilter(FilterBuilders.geoBoundingBoxFilter("additionalLocation").topLeft("52, -1").bottomRight("50,1"));
//When
List<AuthorMarkerAnnotatedEntity> geoAuthorsForGeoCriteria = elasticsearchTemplate.queryForList(queryBuilder.build(), AuthorMarkerAnnotatedEntity.class);
//Then
assertThat(geoAuthorsForGeoCriteria.size(), is(3));
}
@Test
public void shouldFindAuthorMarkersInBoxForGivenCriteriaQueryUsingGeoEnvelop() {
//given
loadClassBaseEntities();
CriteriaQuery geoLocationCriteriaQuery3 = new CriteriaQuery(
new Criteria("location").bbox(
new GeoEnvelope(new GeoPoint(53.5171d, 0),
new GeoPoint(49.5171d, 0.2062d))));
//when
List<AuthorMarkerEntity> geoAuthorsForGeoCriteria3 = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery3, AuthorMarkerEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria3.size(), is(2));
assertThat(geoAuthorsForGeoCriteria3, containsInAnyOrder(hasProperty("name", equalTo("Mohsin Husen")), hasProperty("name", equalTo("Rizwan Idrees"))));
}
@Test
public void shouldFindAuthorMarkersInBoxForGivenCriteriaQueryUsingString() {
//given
loadClassBaseEntities();
CriteriaQuery geoLocationCriteriaQuery3 = new CriteriaQuery(
new Criteria("location").bbox("53.5171d, 0", "49.5171d, 0.2062d"));
//when
List<AuthorMarkerEntity> geoAuthorsForGeoCriteria3 = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery3, AuthorMarkerEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria3.size(), is(2));
assertThat(geoAuthorsForGeoCriteria3, containsInAnyOrder(hasProperty("name", equalTo("Mohsin Husen")), hasProperty("name", equalTo("Rizwan Idrees"))));
}
@Test
public void shouldFindAuthorMarkersInBoxForGivenCriteriaQueryUsingGeoPoints() {
//given
loadClassBaseEntities();
CriteriaQuery geoLocationCriteriaQuery3 = new CriteriaQuery(
new Criteria("location").bbox(
new GeoPoint(53.5171d, 0),
new GeoPoint(49.5171d, 0.2062d)));
//when
List<AuthorMarkerEntity> geoAuthorsForGeoCriteria3 = elasticsearchTemplate.queryForList(geoLocationCriteriaQuery3, AuthorMarkerEntity.class);
//then
assertThat(geoAuthorsForGeoCriteria3.size(), is(2));
assertThat(geoAuthorsForGeoCriteria3, containsInAnyOrder(hasProperty("name", equalTo("Mohsin Husen")), hasProperty("name", equalTo("Rizwan Idrees"))));
}
}

View File

@ -5,10 +5,8 @@
xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<elasticsearch:node-client id="client" local="true" cluster-name="testCluster" http-enabled="false" />-->
<elasticsearch:transport-client id="client" cluster-name="elasticsearch" cluster-nodes="127.0.1.1:9300" />
<elasticsearch:node-client id="client" local="true" cluster-name="testCluster" http-enabled="false" />
<!--<elasticsearch:transport-client id="client" cluster-name="elasticsearch" cluster-nodes="127.0.1.1:9300" />-->
</beans>