mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-23 20:42:11 +00:00
Merge branch 'geo_location'
This commit is contained in:
commit
7e9f12cc9c
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Documented
|
||||||
|
public @interface GeoPointField {
|
||||||
|
|
||||||
|
}
|
@ -46,6 +46,9 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
private Boolean clientIgnoreClusterName;
|
private Boolean clientIgnoreClusterName;
|
||||||
private String clientPingTimeout;
|
private String clientPingTimeout;
|
||||||
private String clientNodesSamplerInterval;
|
private String clientNodesSamplerInterval;
|
||||||
|
private Boolean clientIgnoreClusterName;
|
||||||
|
private String clientPingTimeout;
|
||||||
|
private String clientNodesSamplerInterval;
|
||||||
private TransportClient client;
|
private TransportClient client;
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
static final String COLON = ":";
|
static final String COLON = ":";
|
||||||
@ -118,6 +121,8 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
this.clusterName = clusterName;
|
this.clusterName = clusterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public void setClientTransportSniff(Boolean clientTransportSniff) {
|
public void setClientTransportSniff(Boolean clientTransportSniff) {
|
||||||
this.clientTransportSniff = clientTransportSniff;
|
this.clientTransportSniff = clientTransportSniff;
|
||||||
}
|
}
|
||||||
@ -146,6 +151,30 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
|
|||||||
this.clientIgnoreClusterName = clientIgnoreClusterName;
|
this.clientIgnoreClusterName = clientIgnoreClusterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClientNodesSamplerInterval() {
|
||||||
|
return clientNodesSamplerInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) {
|
||||||
|
this.clientNodesSamplerInterval = clientNodesSamplerInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientPingTimeout() {
|
||||||
|
return clientPingTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientPingTimeout(String clientPingTimeout) {
|
||||||
|
this.clientPingTimeout = clientPingTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getClientIgnoreClusterName() {
|
||||||
|
return clientIgnoreClusterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) {
|
||||||
|
this.clientIgnoreClusterName = clientIgnoreClusterName;
|
||||||
|
}
|
||||||
|
|
||||||
public void setProperties(Properties properties) {
|
public void setProperties(Properties properties) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.index.query.*;
|
||||||
|
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||||
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
|
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.query.FilterBuilders.*;
|
||||||
|
import static org.springframework.data.elasticsearch.core.query.Criteria.OperationKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CriteriaFilterProcessor
|
||||||
|
*
|
||||||
|
* @author Franck Marchand
|
||||||
|
*/
|
||||||
|
class CriteriaFilterProcessor {
|
||||||
|
|
||||||
|
|
||||||
|
FilterBuilder createFilterFromCriteria(Criteria criteria) {
|
||||||
|
List<FilterBuilder> fbList = new LinkedList<FilterBuilder>();
|
||||||
|
FilterBuilder filter = null;
|
||||||
|
|
||||||
|
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
|
||||||
|
|
||||||
|
while (chainIterator.hasNext()) {
|
||||||
|
FilterBuilder fb = null;
|
||||||
|
Criteria chainedCriteria = chainIterator.next();
|
||||||
|
if (chainedCriteria.isOr()) {
|
||||||
|
fb = orFilter(createFilterFragmentForCriteria(chainedCriteria).toArray(new FilterBuilder[]{}));
|
||||||
|
fbList.add(fb);
|
||||||
|
} else if (chainedCriteria.isNegating()) {
|
||||||
|
List<FilterBuilder> negationFilters = buildNegationFilter(criteria.getField().getName(), criteria.getFilterCriteriaEntries().iterator());
|
||||||
|
|
||||||
|
if (!negationFilters.isEmpty()) {
|
||||||
|
fbList.addAll(negationFilters);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fbList.addAll(createFilterFragmentForCriteria(chainedCriteria));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fbList.isEmpty()) {
|
||||||
|
if (fbList.size() == 1) {
|
||||||
|
filter = fbList.get(0);
|
||||||
|
} else {
|
||||||
|
filter = andFilter(fbList.toArray(new FilterBuilder[]{}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<FilterBuilder> createFilterFragmentForCriteria(Criteria chainedCriteria) {
|
||||||
|
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getFilterCriteriaEntries().iterator();
|
||||||
|
List<FilterBuilder> filterList = new LinkedList<FilterBuilder>();
|
||||||
|
|
||||||
|
String fieldName = chainedCriteria.getField().getName();
|
||||||
|
Assert.notNull(fieldName, "Unknown field");
|
||||||
|
FilterBuilder filter = null;
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Criteria.CriteriaEntry entry = it.next();
|
||||||
|
filter = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
|
||||||
|
filterList.add(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private FilterBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
FilterBuilder filter = null;
|
||||||
|
|
||||||
|
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 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");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BBOX: {
|
||||||
|
filter = geoBoundingBoxFilter(fieldName);
|
||||||
|
|
||||||
|
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.");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
|
||||||
|
Assert.isTrue(value instanceof GeoBox, "single-element of a geo bbox filter must be type of GeoEnvelop");
|
||||||
|
GeoBox geoBBox = (GeoBox) 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()) {
|
||||||
|
Criteria.CriteriaEntry criteriaEntry = it.next();
|
||||||
|
FilterBuilder notFilter = notFilter(processCriteriaEntry(criteriaEntry.getKey(), criteriaEntry.getValue(), fieldName));
|
||||||
|
notFilterList.add(notFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return notFilterList;
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,8 @@ import org.springframework.data.elasticsearch.core.query.Criteria;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.*;
|
import static org.elasticsearch.index.query.QueryBuilders.*;
|
||||||
@ -32,106 +34,141 @@ import static org.springframework.data.elasticsearch.core.query.Criteria.Operati
|
|||||||
*
|
*
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Franck Marchand
|
||||||
*/
|
*/
|
||||||
class CriteriaQueryProcessor {
|
class CriteriaQueryProcessor {
|
||||||
|
|
||||||
QueryBuilder createQueryFromCriteria(Criteria criteria) {
|
|
||||||
BoolQueryBuilder query = boolQuery();
|
|
||||||
|
|
||||||
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
|
QueryBuilder createQueryFromCriteria(Criteria criteria) {
|
||||||
while (chainIterator.hasNext()) {
|
if(criteria == null)
|
||||||
Criteria chainedCriteria = chainIterator.next();
|
return null;
|
||||||
if (chainedCriteria.isOr()) {
|
|
||||||
query.should(createQueryFragmentForCriteria(chainedCriteria));
|
|
||||||
} else if (chainedCriteria.isNegating()) {
|
|
||||||
query.mustNot(createQueryFragmentForCriteria(chainedCriteria));
|
|
||||||
} else {
|
|
||||||
query.must(createQueryFragmentForCriteria(chainedCriteria));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
private QueryBuilder createQueryFragmentForCriteria(Criteria chainedCriteria) {
|
List<QueryBuilder> shouldQueryBuilderList = new LinkedList<QueryBuilder>();
|
||||||
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getCriteriaEntries().iterator();
|
List<QueryBuilder> mustNotQueryBuilderList = new LinkedList<QueryBuilder>();
|
||||||
boolean singeEntryCriteria = (chainedCriteria.getCriteriaEntries().size() == 1);
|
List<QueryBuilder> mustQueryBuilderList = new LinkedList<QueryBuilder>();
|
||||||
|
|
||||||
String fieldName = chainedCriteria.getField().getName();
|
|
||||||
Assert.notNull(fieldName, "Unknown field");
|
|
||||||
QueryBuilder query = null;
|
|
||||||
|
|
||||||
if (singeEntryCriteria) {
|
ListIterator<Criteria> chainIterator = criteria.getCriteriaChain().listIterator();
|
||||||
Criteria.CriteriaEntry entry = it.next();
|
while (chainIterator.hasNext()) {
|
||||||
query = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
|
Criteria chainedCriteria = chainIterator.next();
|
||||||
} else {
|
QueryBuilder queryFragmentForCriteria = createQueryFragmentForCriteria(chainedCriteria);
|
||||||
query = boolQuery();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Criteria.CriteriaEntry entry = it.next();
|
|
||||||
((BoolQueryBuilder) query).must(processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addBoost(query, chainedCriteria.getBoost());
|
if(queryFragmentForCriteria!=null) {
|
||||||
return query;
|
if(chainedCriteria.isOr()){
|
||||||
}
|
shouldQueryBuilderList.add(queryFragmentForCriteria);
|
||||||
|
}else if(chainedCriteria.isNegating()){
|
||||||
|
mustNotQueryBuilderList.add(queryFragmentForCriteria);
|
||||||
|
}else{
|
||||||
|
mustQueryBuilderList.add(queryFragmentForCriteria);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
|
BoolQueryBuilder query = null;
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
QueryBuilder query = null;
|
|
||||||
|
|
||||||
switch (key) {
|
if(!shouldQueryBuilderList.isEmpty() || !mustNotQueryBuilderList.isEmpty() || !mustQueryBuilderList.isEmpty()) {
|
||||||
case EQUALS:
|
|
||||||
query = fieldQuery(fieldName, value);
|
|
||||||
break;
|
|
||||||
case CONTAINS:
|
|
||||||
query = fieldQuery(fieldName, "*" + value + "*").analyzeWildcard(true);
|
|
||||||
break;
|
|
||||||
case STARTS_WITH:
|
|
||||||
query = fieldQuery(fieldName, value + "*").analyzeWildcard(true);
|
|
||||||
break;
|
|
||||||
case ENDS_WITH:
|
|
||||||
query = fieldQuery(fieldName, "*" + value).analyzeWildcard(true);
|
|
||||||
break;
|
|
||||||
case EXPRESSION:
|
|
||||||
query = queryString((String) value).field(fieldName);
|
|
||||||
break;
|
|
||||||
case BETWEEN:
|
|
||||||
Object[] ranges = (Object[]) value;
|
|
||||||
query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]);
|
|
||||||
break;
|
|
||||||
case FUZZY:
|
|
||||||
query = fuzzyQuery(fieldName, (String) value);
|
|
||||||
break;
|
|
||||||
case IN:
|
|
||||||
query = boolQuery();
|
|
||||||
Iterable<Object> collection = (Iterable<Object>) value;
|
|
||||||
for (Object item : collection) {
|
|
||||||
((BoolQueryBuilder) query).should(fieldQuery(fieldName, item));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return query;
|
query = boolQuery();
|
||||||
}
|
|
||||||
|
|
||||||
private QueryBuilder buildNegationQuery(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
|
for(QueryBuilder qb : shouldQueryBuilderList) {
|
||||||
BoolQueryBuilder notQuery = boolQuery();
|
query.should(qb);
|
||||||
while (it.hasNext()) {
|
}
|
||||||
notQuery.mustNot(fieldQuery(fieldName, it.next().getValue()));
|
for(QueryBuilder qb : mustNotQueryBuilderList) {
|
||||||
}
|
query.mustNot(qb);
|
||||||
return notQuery;
|
}
|
||||||
}
|
for(QueryBuilder qb : mustQueryBuilderList) {
|
||||||
|
query.must(qb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addBoost(QueryBuilder query, float boost) {
|
return query;
|
||||||
if (Float.isNaN(boost)) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (query instanceof BoostableQueryBuilder) {
|
|
||||||
((BoostableQueryBuilder) query).boost(boost);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
private QueryBuilder createQueryFragmentForCriteria(Criteria chainedCriteria) {
|
||||||
|
if(chainedCriteria.getQueryCriteriaEntries().isEmpty())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Iterator<Criteria.CriteriaEntry> it = chainedCriteria.getQueryCriteriaEntries().iterator();
|
||||||
|
boolean singeEntryCriteria = (chainedCriteria.getQueryCriteriaEntries().size() == 1);
|
||||||
|
|
||||||
|
String fieldName = chainedCriteria.getField().getName();
|
||||||
|
Assert.notNull(fieldName,"Unknown field");
|
||||||
|
QueryBuilder query = null;
|
||||||
|
|
||||||
|
if(singeEntryCriteria){
|
||||||
|
Criteria.CriteriaEntry entry = it.next();
|
||||||
|
query = processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName);
|
||||||
|
}else{
|
||||||
|
query = boolQuery();
|
||||||
|
while (it.hasNext()){
|
||||||
|
Criteria.CriteriaEntry entry = it.next();
|
||||||
|
((BoolQueryBuilder)query).must(processCriteriaEntry(entry.getKey(), entry.getValue(), fieldName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addBoost(query, chainedCriteria.getBoost());
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private QueryBuilder processCriteriaEntry(OperationKey key, Object value, String fieldName) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
QueryBuilder query = null;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case EQUALS:
|
||||||
|
query = fieldQuery(fieldName, value);
|
||||||
|
break;
|
||||||
|
case CONTAINS:
|
||||||
|
query = fieldQuery(fieldName, "*" + value + "*").analyzeWildcard(true);
|
||||||
|
break;
|
||||||
|
case STARTS_WITH:
|
||||||
|
query = fieldQuery(fieldName, value + "*").analyzeWildcard(true);
|
||||||
|
break;
|
||||||
|
case ENDS_WITH:
|
||||||
|
query = fieldQuery(fieldName, "*" + value).analyzeWildcard(true);
|
||||||
|
break;
|
||||||
|
case EXPRESSION:
|
||||||
|
query = queryString((String) value).field(fieldName);
|
||||||
|
break;
|
||||||
|
case BETWEEN:
|
||||||
|
Object[] ranges = (Object[]) value;
|
||||||
|
query = rangeQuery(fieldName).from(ranges[0]).to(ranges[1]);
|
||||||
|
break;
|
||||||
|
case FUZZY:
|
||||||
|
query = fuzzyQuery(fieldName, (String) value);
|
||||||
|
break;
|
||||||
|
case IN:
|
||||||
|
query = boolQuery();
|
||||||
|
Iterable<Object> collection = (Iterable<Object>) value;
|
||||||
|
for (Object item : collection) {
|
||||||
|
((BoolQueryBuilder) query).should(fieldQuery(fieldName, item));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private QueryBuilder buildNegationQuery(String fieldName, Iterator<Criteria.CriteriaEntry> it) {
|
||||||
|
BoolQueryBuilder notQuery = boolQuery();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
notQuery.mustNot(fieldQuery(fieldName, it.next().getValue()));
|
||||||
|
}
|
||||||
|
return notQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addBoost(QueryBuilder query, float boost) {
|
||||||
|
if (Float.isNaN(boost)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (query instanceof BoostableQueryBuilder) {
|
||||||
|
((BoostableQueryBuilder) query).boost(boost);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,16 @@ public interface ElasticsearchOperations {
|
|||||||
*/
|
*/
|
||||||
<T> List<T> queryForList(StringQuery query, Class<T> clazz);
|
<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
|
* Execute the query against elasticsearch and return ids
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,9 @@ import org.elasticsearch.client.Requests;
|
|||||||
import org.elasticsearch.common.collect.MapBuilder;
|
import org.elasticsearch.common.collect.MapBuilder;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.index.query.FilterBuilder;
|
||||||
import org.elasticsearch.index.query.QueryBuilder;
|
import org.elasticsearch.index.query.QueryBuilder;
|
||||||
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.facet.Facet;
|
import org.elasticsearch.search.facet.Facet;
|
||||||
import org.elasticsearch.search.facet.FacetBuilder;
|
import org.elasticsearch.search.facet.FacetBuilder;
|
||||||
@ -171,6 +173,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
return queryForPage(query, clazz).getContent();
|
return queryForPage(query, clazz).getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> queryForList(SearchQuery query, Class<T> clazz) {
|
||||||
|
return queryForPage(query, clazz).getContent();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> List<String> queryForIds(SearchQuery query) {
|
public <T> List<String> queryForIds(SearchQuery query) {
|
||||||
SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields();
|
SearchRequestBuilder request = prepareSearch(query).setQuery(query.getQuery()).setNoFields();
|
||||||
@ -183,8 +190,21 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
|
||||||
QueryBuilder query = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
QueryBuilder elasticsearchQuery = new CriteriaQueryProcessor().createQueryFromCriteria(criteriaQuery.getCriteria());
|
||||||
SearchResponse response = prepareSearch(criteriaQuery, clazz).setQuery(query).execute().actionGet();
|
FilterBuilder elasticsearchFilter = new CriteriaFilterProcessor().createFilterFromCriteria(criteriaQuery.getCriteria());
|
||||||
|
SearchRequestBuilder searchRequestBuilder = prepareSearch(criteriaQuery, clazz);
|
||||||
|
|
||||||
|
if (elasticsearchQuery != null) {
|
||||||
|
searchRequestBuilder.setQuery(elasticsearchQuery);
|
||||||
|
} else {
|
||||||
|
searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elasticsearchFilter != null)
|
||||||
|
searchRequestBuilder.setFilter(elasticsearchFilter);
|
||||||
|
|
||||||
|
SearchResponse response = searchRequestBuilder
|
||||||
|
.execute().actionGet();
|
||||||
return mapResults(response, clazz, criteriaQuery.getPageable());
|
return mapResults(response, clazz, criteriaQuery.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core;
|
|||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.springframework.data.elasticsearch.annotations.*;
|
import org.springframework.data.elasticsearch.annotations.*;
|
||||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
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.mapping.model.SimpleTypeHolder;
|
||||||
import org.springframework.data.util.ClassTypeInformation;
|
import org.springframework.data.util.ClassTypeInformation;
|
||||||
import org.springframework.data.util.TypeInformation;
|
import org.springframework.data.util.TypeInformation;
|
||||||
@ -47,6 +48,7 @@ class MappingBuilder {
|
|||||||
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
|
public static final String INDEX_VALUE_NOT_ANALYZED = "not_analyzed";
|
||||||
public static final String TYPE_VALUE_STRING = "string";
|
public static final String TYPE_VALUE_STRING = "string";
|
||||||
public static final String TYPE_VALUE_OBJECT = "object";
|
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();
|
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = new SimpleTypeHolder();
|
||||||
|
|
||||||
@ -71,8 +73,15 @@ class MappingBuilder {
|
|||||||
if (isEntity(field)) {
|
if (isEntity(field)) {
|
||||||
mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
|
mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
Field singleField = field.getAnnotation(Field.class);
|
Field singleField = field.getAnnotation(Field.class);
|
||||||
MultiField multiField = field.getAnnotation(MultiField.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)) {
|
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
|
||||||
applyDefaultIdFieldMapping(xContentBuilder, field);
|
applyDefaultIdFieldMapping(xContentBuilder, field);
|
||||||
} else if (multiField != null) {
|
} else if (multiField != null) {
|
||||||
@ -88,6 +97,12 @@ class MappingBuilder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void applyGeoPointFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field) throws IOException {
|
||||||
|
xContentBuilder.startObject(field.getName());
|
||||||
|
xContentBuilder.field(FIELD_TYPE, TYPE_VALUE_GEO_POINT)
|
||||||
|
.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
xContentBuilder.startObject(field.getName())
|
xContentBuilder.startObject(field.getName())
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geo bbox used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
|
||||||
|
*
|
||||||
|
* @author Franck Marchand
|
||||||
|
*/
|
||||||
|
public class GeoBox {
|
||||||
|
|
||||||
|
private GeoPoint topLeft;
|
||||||
|
private GeoPoint bottomRight;
|
||||||
|
|
||||||
|
public GeoBox(GeoPoint topLeft, GeoPoint bottomRight) {
|
||||||
|
this.topLeft = topLeft;
|
||||||
|
this.bottomRight = bottomRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeoPoint getTopLeft() {
|
||||||
|
return topLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeoPoint getBottomRight() {
|
||||||
|
return bottomRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* geo-location used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
|
||||||
|
*
|
||||||
|
* @author Franck Marchand
|
||||||
|
*/
|
||||||
|
public class GeoPoint {
|
||||||
|
|
||||||
|
private double lat;
|
||||||
|
private double lon;
|
||||||
|
|
||||||
|
private GeoPoint() {
|
||||||
|
//required by mapper to instantiate object
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeoPoint(double latitude, double longitude) {
|
||||||
|
this.lat = latitude;
|
||||||
|
this.lon = longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLat() {
|
||||||
|
return lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLon() {
|
||||||
|
return lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
|
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||||
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,418 +35,504 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Franck Marchand
|
||||||
*/
|
*/
|
||||||
public class Criteria {
|
public class Criteria {
|
||||||
|
|
||||||
public static final String WILDCARD = "*";
|
public static final String WILDCARD = "*";
|
||||||
public static final String CRITERIA_VALUE_SEPERATOR = " ";
|
public static final String CRITERIA_VALUE_SEPERATOR = " ";
|
||||||
|
|
||||||
private static final String OR_OPERATOR = " OR ";
|
private static final String OR_OPERATOR = " OR ";
|
||||||
private static final String AND_OPERATOR = " AND ";
|
private static final String AND_OPERATOR = " AND ";
|
||||||
|
|
||||||
private Field field;
|
private Field field;
|
||||||
private float boost = Float.NaN;
|
private float boost = Float.NaN;
|
||||||
private boolean negating = false;
|
private boolean negating = false;
|
||||||
|
|
||||||
private List<Criteria> criteriaChain = new ArrayList<Criteria>(1);
|
private List<Criteria> criteriaChain = new ArrayList<Criteria>(1);
|
||||||
|
|
||||||
private Set<CriteriaEntry> criteria = new LinkedHashSet<CriteriaEntry>();
|
private Set<CriteriaEntry> queryCriteria = new LinkedHashSet<CriteriaEntry>();
|
||||||
|
|
||||||
public Criteria() {
|
private Set<CriteriaEntry> filterCriteria = new LinkedHashSet<CriteriaEntry>();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
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 Criteria for the given field
|
* Creates a new CriterSimpleFieldia for the Filed with provided name
|
||||||
*
|
*
|
||||||
* @param field
|
* @param fieldname
|
||||||
*/
|
*/
|
||||||
public Criteria(Field field) {
|
public Criteria(String fieldname) {
|
||||||
Assert.notNull(field, "Field for criteria must not be null");
|
this(new SimpleField(fieldname));
|
||||||
Assert.hasText(field.getName(), "Field.name for criteria must not be null/empty");
|
}
|
||||||
|
|
||||||
this.criteriaChain.add(this);
|
/**
|
||||||
this.field = field;
|
* 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");
|
||||||
|
|
||||||
protected Criteria(List<Criteria> criteriaChain, String fieldname) {
|
this.criteriaChain.add(this);
|
||||||
this(criteriaChain, new SimpleField(fieldname));
|
this.field = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Criteria(List<Criteria> criteriaChain, Field field) {
|
protected Criteria(List<Criteria> criteriaChain, String fieldname) {
|
||||||
Assert.notNull(criteriaChain, "CriteriaChain must not be null");
|
this(criteriaChain, new SimpleField(fieldname));
|
||||||
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);
|
protected Criteria(List<Criteria> criteriaChain, Field field) {
|
||||||
this.criteriaChain.add(this);
|
Assert.notNull(criteriaChain, "CriteriaChain must not be null");
|
||||||
this.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.addAll(criteriaChain);
|
||||||
* Static factory method to create a new Criteria for field with given name
|
this.criteriaChain.add(this);
|
||||||
*
|
this.field = field;
|
||||||
* @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
|
* Static factory method to create a new Criteria for field with given name
|
||||||
*
|
*
|
||||||
* @param field
|
* @param field
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static Criteria where(Field field) {
|
public static Criteria where(String field) {
|
||||||
return new Criteria(field);
|
return where(new SimpleField(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain using {@code AND}
|
* Static factory method to create a new Criteria for provided field
|
||||||
*
|
*
|
||||||
* @param field
|
* @param field
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria and(Field field) {
|
public static Criteria where(Field field) {
|
||||||
return new Criteria(this.criteriaChain, field);
|
return new Criteria(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain using {@code AND}
|
* Chain using {@code AND}
|
||||||
*
|
*
|
||||||
* @param fieldName
|
* @param field
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria and(String fieldName) {
|
public Criteria and(Field field) {
|
||||||
return new Criteria(this.criteriaChain, fieldName);
|
return new Criteria(this.criteriaChain, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain using {@code AND}
|
* Chain using {@code AND}
|
||||||
*
|
*
|
||||||
* @param criteria
|
* @param fieldName
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria and(Criteria criteria) {
|
public Criteria and(String fieldName) {
|
||||||
this.criteriaChain.add(criteria);
|
return new Criteria(this.criteriaChain, fieldName);
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain using {@code AND}
|
* Chain using {@code AND}
|
||||||
*
|
*
|
||||||
* @param criterias
|
* @param criteria
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria and(Criteria... criterias) {
|
public Criteria and(Criteria criteria) {
|
||||||
this.criteriaChain.addAll(Arrays.asList(criterias));
|
this.criteriaChain.add(criteria);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain using {@code OR}
|
* Chain using {@code AND}
|
||||||
*
|
*
|
||||||
* @param field
|
* @param criterias
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria or(Field field) {
|
public Criteria and(Criteria... criterias) {
|
||||||
return new OrCriteria(this.criteriaChain, field);
|
this.criteriaChain.addAll(Arrays.asList(criterias));
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain using {@code OR}
|
* Chain using {@code OR}
|
||||||
*
|
*
|
||||||
* @param criteria
|
* @param field
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria or(Criteria criteria) {
|
public Criteria or(Field field) {
|
||||||
Assert.notNull(criteria, "Cannot chain 'null' criteria.");
|
return new OrCriteria(this.criteriaChain, field);
|
||||||
|
}
|
||||||
|
|
||||||
Criteria orConnectedCritiera = new OrCriteria(this.criteriaChain, criteria.getField());
|
/**
|
||||||
orConnectedCritiera.criteria.addAll(criteria.criteria);
|
* Chain using {@code OR}
|
||||||
return orConnectedCritiera;
|
*
|
||||||
}
|
* @param criteria
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Criteria or(Criteria criteria) {
|
||||||
|
Assert.notNull(criteria, "Cannot chain 'null' criteria.");
|
||||||
|
|
||||||
/**
|
Criteria orConnectedCritiera = new OrCriteria(this.criteriaChain, criteria.getField());
|
||||||
* Chain using {@code OR}
|
orConnectedCritiera.queryCriteria.addAll(criteria.queryCriteria);
|
||||||
*
|
return orConnectedCritiera;
|
||||||
* @param fieldName
|
}
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Criteria or(String fieldName) {
|
|
||||||
return or(new SimpleField(fieldName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry without any wildcards
|
* Chain using {@code OR}
|
||||||
*
|
*
|
||||||
* @param o
|
* @param fieldName
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria is(Object o) {
|
public Criteria or(String fieldName) {
|
||||||
criteria.add(new CriteriaEntry(OperationKey.EQUALS, o));
|
return or(new SimpleField(fieldName));
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry with leading and trailing wildcards <br/>
|
* Crates new CriteriaEntry without any wildcards
|
||||||
* <strong>NOTE: </strong> mind your schema as leading wildcards may not be supported and/or execution might be slow.
|
*
|
||||||
*
|
* @param o
|
||||||
* @param s
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
public Criteria is(Object o) {
|
||||||
public Criteria contains(String s) {
|
queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o));
|
||||||
assertNoBlankInWildcardedQuery(s, true, true);
|
return this;
|
||||||
criteria.add(new CriteriaEntry(OperationKey.CONTAINS, s));
|
}
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry with trailing wildcard
|
* 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
|
* @param s
|
||||||
*/
|
* @return
|
||||||
public Criteria startsWith(String s) {
|
*/
|
||||||
assertNoBlankInWildcardedQuery(s, true, false);
|
public Criteria contains(String s) {
|
||||||
criteria.add(new CriteriaEntry(OperationKey.STARTS_WITH, s));
|
assertNoBlankInWildcardedQuery(s, true, true);
|
||||||
return this;
|
queryCriteria.add(new CriteriaEntry(OperationKey.CONTAINS, s));
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry with leading wildcard <br />
|
* Crates new CriteriaEntry with trailing wildcard
|
||||||
* <strong>NOTE: </strong> mind your schema and execution times as leading wildcards may not be supported.
|
*
|
||||||
*
|
* @param s
|
||||||
* @param s
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
public Criteria startsWith(String s) {
|
||||||
public Criteria endsWith(String s) {
|
assertNoBlankInWildcardedQuery(s, true, false);
|
||||||
assertNoBlankInWildcardedQuery(s, false, true);
|
queryCriteria.add(new CriteriaEntry(OperationKey.STARTS_WITH, s));
|
||||||
criteria.add(new CriteriaEntry(OperationKey.ENDS_WITH, s));
|
return this;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry with trailing -
|
* Crates new CriteriaEntry with leading wildcard <br />
|
||||||
*
|
* <strong>NOTE: </strong> mind your schema and execution times as leading wildcards may not be supported.
|
||||||
* @return
|
*
|
||||||
*/
|
* @param s
|
||||||
public Criteria not() {
|
* @return
|
||||||
this.negating = true;
|
*/
|
||||||
return this;
|
public Criteria endsWith(String s) {
|
||||||
}
|
assertNoBlankInWildcardedQuery(s, false, true);
|
||||||
|
queryCriteria.add(new CriteriaEntry(OperationKey.ENDS_WITH, s));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry with trailing ~
|
* Crates new CriteriaEntry with trailing -
|
||||||
*
|
*
|
||||||
* @param s
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
public Criteria not() {
|
||||||
public Criteria fuzzy(String s) {
|
this.negating = true;
|
||||||
criteria.add(new CriteriaEntry(OperationKey.FUZZY, s));
|
return this;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry allowing native elasticsearch expressions
|
* Crates new CriteriaEntry with trailing ~
|
||||||
*
|
*
|
||||||
* @param s
|
* @param s
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria expression(String s) {
|
public Criteria fuzzy(String s) {
|
||||||
criteria.add(new CriteriaEntry(OperationKey.EXPRESSION, s));
|
queryCriteria.add(new CriteriaEntry(OperationKey.FUZZY, s));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boost positive hit with given factor. eg. ^2.3
|
* Crates new CriteriaEntry allowing native elasticsearch expressions
|
||||||
*
|
*
|
||||||
* @param boost
|
* @param s
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria boost(float boost) {
|
public Criteria expression(String s) {
|
||||||
if (boost < 0) {
|
queryCriteria.add(new CriteriaEntry(OperationKey.EXPRESSION, s));
|
||||||
throw new InvalidDataAccessApiUsageException("Boost must not be negative.");
|
return this;
|
||||||
}
|
}
|
||||||
this.boost = boost;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO upperBound]}
|
* Boost positive hit with given factor. eg. ^2.3
|
||||||
*
|
*
|
||||||
* @param lowerBound
|
* @param boost
|
||||||
* @param upperBound
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
public Criteria boost(float boost) {
|
||||||
public Criteria between(Object lowerBound, Object upperBound) {
|
if (boost < 0) {
|
||||||
if (lowerBound == null && upperBound == null) {
|
throw new InvalidDataAccessApiUsageException("Boost must not be negative.");
|
||||||
throw new InvalidDataAccessApiUsageException("Range [* TO *] is not allowed");
|
}
|
||||||
}
|
this.boost = boost;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
criteria.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[] { lowerBound, upperBound }));
|
/**
|
||||||
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");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
queryCriteria.add(new CriteriaEntry(OperationKey.BETWEEN, new Object[]{lowerBound, upperBound}));
|
||||||
* Crates new CriteriaEntry for {@code RANGE [* TO upperBound]}
|
return this;
|
||||||
*
|
}
|
||||||
* @param upperBound
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Criteria lessThanEqual(Object upperBound) {
|
|
||||||
between(null, upperBound);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO *]}
|
* Crates new CriteriaEntry for {@code RANGE [* TO upperBound]}
|
||||||
*
|
*
|
||||||
* @param lowerBound
|
* @param upperBound
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria greaterThanEqual(Object lowerBound) {
|
public Criteria lessThanEqual(Object upperBound) {
|
||||||
between(lowerBound, null);
|
between(null, upperBound);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
|
* Crates new CriteriaEntry for {@code RANGE [lowerBound TO *]}
|
||||||
*
|
*
|
||||||
* @param values
|
* @param lowerBound
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria in(Object... values) {
|
public Criteria greaterThanEqual(Object lowerBound) {
|
||||||
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
|
between(lowerBound, null);
|
||||||
throw new InvalidDataAccessApiUsageException("At least one element "
|
return this;
|
||||||
+ (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 ...)}
|
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
|
||||||
*
|
*
|
||||||
* @param values the collection containing the values to match against
|
* @param values
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Criteria in(Iterable<?> values) {
|
public Criteria in(Object... values) {
|
||||||
Assert.notNull(values, "Collection of 'in' values must not be null");
|
if (values.length == 0 || (values.length > 1 && values[1] instanceof Collection)) {
|
||||||
criteria.add(new CriteriaEntry(OperationKey.IN, values));
|
throw new InvalidDataAccessApiUsageException("At least one element "
|
||||||
return this;
|
+ (values.length > 0 ? ("of argument of type " + values[1].getClass().getName()) : "")
|
||||||
}
|
+ " has to be present.");
|
||||||
|
}
|
||||||
|
return in(Arrays.asList(values));
|
||||||
|
}
|
||||||
|
|
||||||
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
|
/**
|
||||||
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
|
* Crates new CriteriaEntry for multiple values {@code (arg0 arg1 arg2 ...)}
|
||||||
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
|
*
|
||||||
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use epxression or mulitple clauses instead.");
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field targeted by this Criteria
|
* Creates new CriteriaEntry for {@code location WITHIN distance}
|
||||||
*
|
*
|
||||||
* @return
|
* @param location {@link org.springframework.data.elasticsearch.core.geo.GeoPoint} center coordinates
|
||||||
*/
|
* @param distance {@link String} radius as a string (e.g. : '100km').
|
||||||
public Field getField() {
|
* Distance unit :
|
||||||
return this.field;
|
* either mi/miles or km can be set
|
||||||
}
|
* @return Criteria the chaind criteria with the new 'within' criteria included.
|
||||||
|
*/
|
||||||
|
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}));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<CriteriaEntry> getCriteriaEntries() {
|
/**
|
||||||
return Collections.unmodifiableSet(this.criteria);
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conjunction to be used with this criteria (AND | OR)
|
* Creates new CriteriaEntry for {@code location BBOX bounding box}
|
||||||
*
|
*
|
||||||
* @return
|
* @param bbox {@link org.springframework.data.elasticsearch.core.geo.GeoBox} bounding box(left top corner + right bottom corner)
|
||||||
*/
|
* @return Criteria the chaind criteria with the new 'bbox' criteria included.
|
||||||
public String getConjunctionOperator() {
|
*/
|
||||||
return AND_OPERATOR;
|
public Criteria bbox(GeoBox bbox) {
|
||||||
}
|
Assert.notNull(bbox, "bbox value for bbox criteria must not be null");
|
||||||
|
filterCriteria.add(new CriteriaEntry(OperationKey.BBOX, new Object[]{bbox}));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Criteria> getCriteriaChain() {
|
|
||||||
return Collections.unmodifiableList(this.criteriaChain);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNegating() {
|
/**
|
||||||
return this.negating;
|
* 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 boolean isAnd() {
|
/**
|
||||||
return AND_OPERATOR == getConjunctionOperator();
|
* 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 boolean isOr() {
|
private void assertNoBlankInWildcardedQuery(String searchString, boolean leadingWildcard, boolean trailingWildcard) {
|
||||||
return OR_OPERATOR == getConjunctionOperator();
|
if (StringUtils.contains(searchString, CRITERIA_VALUE_SEPERATOR)) {
|
||||||
}
|
throw new InvalidDataAccessApiUsageException("Cannot constructQuery '" + (leadingWildcard ? "*" : "") + "\""
|
||||||
|
+ searchString + "\"" + (trailingWildcard ? "*" : "") + "'. Use epxression or mulitple clauses instead.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public float getBoost() {
|
/**
|
||||||
return this.boost;
|
* Field targeted by this Criteria
|
||||||
}
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Field getField() {
|
||||||
|
return this.field;
|
||||||
|
}
|
||||||
|
|
||||||
static class OrCriteria extends Criteria {
|
public Set<CriteriaEntry> getQueryCriteriaEntries() {
|
||||||
|
return Collections.unmodifiableSet(this.queryCriteria);
|
||||||
|
}
|
||||||
|
|
||||||
public OrCriteria() {
|
public Set<CriteriaEntry> getFilterCriteriaEntries() {
|
||||||
super();
|
return Collections.unmodifiableSet(this.filterCriteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrCriteria(Field field) {
|
public Set<CriteriaEntry> getFilterCriteria() {
|
||||||
super(field);
|
return filterCriteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrCriteria(List<Criteria> criteriaChain, Field field) {
|
/**
|
||||||
super(criteriaChain, field);
|
* Conjunction to be used with this criteria (AND | OR)
|
||||||
}
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getConjunctionOperator() {
|
||||||
|
return AND_OPERATOR;
|
||||||
|
}
|
||||||
|
|
||||||
public OrCriteria(List<Criteria> criteriaChain, String fieldname) {
|
public List<Criteria> getCriteriaChain() {
|
||||||
super(criteriaChain, fieldname);
|
return Collections.unmodifiableList(this.criteriaChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrCriteria(String fieldname) {
|
public boolean isNegating() {
|
||||||
super(fieldname);
|
return this.negating;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean isAnd() {
|
||||||
public String getConjunctionOperator() {
|
return AND_OPERATOR == getConjunctionOperator();
|
||||||
return OR_OPERATOR;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
public boolean isOr() {
|
||||||
|
return OR_OPERATOR == getConjunctionOperator();
|
||||||
|
}
|
||||||
|
|
||||||
public enum OperationKey {
|
public float getBoost() {
|
||||||
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN;
|
return this.boost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CriteriaEntry {
|
static class OrCriteria extends Criteria {
|
||||||
|
|
||||||
private OperationKey key;
|
public OrCriteria() {
|
||||||
private Object value;
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
CriteriaEntry(OperationKey key, Object value) {
|
public OrCriteria(Field field) {
|
||||||
this.key = key;
|
super(field);
|
||||||
this.value = value;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public OperationKey getKey() {
|
public OrCriteria(List<Criteria> criteriaChain, Field field) {
|
||||||
return key;
|
super(criteriaChain, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue() {
|
public OrCriteria(List<Criteria> criteriaChain, String fieldname) {
|
||||||
return value;
|
super(criteriaChain, fieldname);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public OrCriteria(String fieldname) {
|
||||||
|
super(fieldname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConjunctionOperator() {
|
||||||
|
return OR_OPERATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OperationKey {
|
||||||
|
EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, EXPRESSION, BETWEEN, FUZZY, IN, WITHIN, BBOX, NEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CriteriaEntry {
|
||||||
|
|
||||||
|
private OperationKey key;
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
CriteriaEntry(OperationKey key, Object value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationKey getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,47 +35,47 @@ public class CriteriaQuery extends AbstractQuery {
|
|||||||
this(criteria, null);
|
this(criteria, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CriteriaQuery(Criteria criteria, Pageable pageable) {
|
public CriteriaQuery(Criteria criteria, Pageable pageable) {
|
||||||
this.criteria = criteria;
|
this.criteria = criteria;
|
||||||
this.pageable = pageable;
|
this.pageable = pageable;
|
||||||
if (pageable != null) {
|
if (pageable != null) {
|
||||||
this.addSort(pageable.getSort());
|
this.addSort(pageable.getSort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Query fromQuery(CriteriaQuery source) {
|
public static final Query fromQuery(CriteriaQuery source) {
|
||||||
return fromQuery(source, new CriteriaQuery());
|
return fromQuery(source, new CriteriaQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends CriteriaQuery> T fromQuery(CriteriaQuery source, T destination) {
|
public static <T extends CriteriaQuery> T fromQuery(CriteriaQuery source, T destination) {
|
||||||
if (source == null || destination == null) {
|
if (source == null || destination == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.getCriteria() != null) {
|
if (source.getCriteria() != null) {
|
||||||
destination.addCriteria(source.getCriteria());
|
destination.addCriteria(source.getCriteria());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source.getSort() != null) {
|
if (source.getSort() != null) {
|
||||||
destination.addSort(source.getSort());
|
destination.addSort(source.getSort());
|
||||||
}
|
}
|
||||||
|
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final <T extends CriteriaQuery> T addCriteria(Criteria criteria) {
|
public final <T extends CriteriaQuery> T addCriteria(Criteria criteria) {
|
||||||
Assert.notNull(criteria, "Cannot add null criteria.");
|
Assert.notNull(criteria, "Cannot add null criteria.");
|
||||||
if (this.criteria == null) {
|
if (this.criteria == null) {
|
||||||
this.criteria = criteria;
|
this.criteria = criteria;
|
||||||
} else {
|
} else {
|
||||||
this.criteria.and(criteria);
|
this.criteria.and(criteria);
|
||||||
}
|
}
|
||||||
return (T) this;
|
return (T) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Criteria getCriteria() {
|
public Criteria getCriteria() {
|
||||||
return this.criteria;
|
return this.criteria;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.apache.commons.collections.CollectionUtils.addAll;
|
import static org.apache.commons.collections.CollectionUtils.addAll;
|
||||||
import static org.springframework.data.elasticsearch.core.query.Query.DEFAULT_PAGE;
|
import static org.springframework.data.elasticsearch.core.query.AbstractQuery.DEFAULT_PAGE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MoreLikeThisQuery
|
* MoreLikeThisQuery
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -49,6 +49,7 @@ import static org.junit.Assert.*;
|
|||||||
/**
|
/**
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Franck Marchand
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
|
||||||
@ -57,12 +58,12 @@ public class ElasticsearchTemplateTests {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ElasticsearchTemplate elasticsearchTemplate;
|
private ElasticsearchTemplate elasticsearchTemplate;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before(){
|
||||||
elasticsearchTemplate.deleteIndex(SampleEntity.class);
|
elasticsearchTemplate.deleteIndex(SampleEntity.class);
|
||||||
elasticsearchTemplate.createIndex(SampleEntity.class);
|
elasticsearchTemplate.createIndex(SampleEntity.class);
|
||||||
elasticsearchTemplate.refresh(SampleEntity.class, true);
|
elasticsearchTemplate.refresh(SampleEntity.class, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnCountForGivenSearchQuery() {
|
public void shouldReturnCountForGivenSearchQuery() {
|
||||||
|
@ -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.annotation.Id;
|
||||||
import org.springframework.data.elasticsearch.annotations.*;
|
import org.springframework.data.elasticsearch.annotations.*;
|
||||||
@ -15,7 +15,7 @@ import static org.springframework.data.elasticsearch.annotations.FieldType.Strin
|
|||||||
* Simple type to test facets
|
* Simple type to test facets
|
||||||
*/
|
*/
|
||||||
@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1", indexStoreType = "memory")
|
@Document(indexName = "articles", type = "article", shards = 1, replicas = 0, refreshInterval = "-1", indexStoreType = "memory")
|
||||||
public class Article {
|
public class ArticleEntity {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
private String id;
|
private String id;
|
||||||
@ -36,11 +36,11 @@ public class Article {
|
|||||||
|
|
||||||
private int score;
|
private int score;
|
||||||
|
|
||||||
public Article() {
|
private ArticleEntity(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Article(String id) {
|
public ArticleEntity(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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.index.query.FilterBuilders;
|
||||||
import org.elasticsearch.search.facet.FacetBuilders;
|
import org.elasticsearch.search.facet.FacetBuilders;
|
||||||
@ -21,8 +21,8 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.elasticsearch.Article;
|
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||||
import org.springframework.data.elasticsearch.ArticleBuilder;
|
import org.springframework.data.elasticsearch.core.FacetedPage;
|
||||||
import org.springframework.data.elasticsearch.core.facet.request.NativeFacetRequest;
|
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.RangeFacetRequestBuilder;
|
||||||
import org.springframework.data.elasticsearch.core.facet.request.TermFacetRequestBuilder;
|
import org.springframework.data.elasticsearch.core.facet.request.TermFacetRequestBuilder;
|
||||||
@ -62,21 +62,21 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
elasticsearchTemplate.deleteIndex(Article.class);
|
elasticsearchTemplate.deleteIndex(ArticleEntity.class);
|
||||||
elasticsearchTemplate.createIndex(Article.class);
|
elasticsearchTemplate.createIndex(ArticleEntity.class);
|
||||||
elasticsearchTemplate.putMapping(Article.class);
|
elasticsearchTemplate.putMapping(ArticleEntity.class);
|
||||||
elasticsearchTemplate.refresh(Article.class, true);
|
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 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 ArticleBuilder("2").title("article three").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addAuthor(MOHSIN_HUSEN).addPublishedYear(YEAR_2000).score(20).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 ArticleBuilder("3").title("article two").addAuthor(RIZWAN_IDREES).addAuthor(ARTUR_KONCZAK).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(30).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 ArticleBuilder("4").title("article one").addAuthor(RIZWAN_IDREES).addPublishedYear(YEAR_2002).addPublishedYear(YEAR_2001).addPublishedYear(YEAR_2000).score(40).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(article1);
|
||||||
elasticsearchTemplate.index(article2);
|
elasticsearchTemplate.index(article2);
|
||||||
elasticsearchTemplate.index(article3);
|
elasticsearchTemplate.index(article3);
|
||||||
elasticsearchTemplate.index(article4);
|
elasticsearchTemplate.index(article4);
|
||||||
elasticsearchTemplate.refresh(Article.class, true);
|
elasticsearchTemplate.refresh(ArticleEntity.class, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -86,7 +86,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
String facetName = "fauthors";
|
String facetName = "fauthors";
|
||||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").build()).build();
|
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").excludeTerms(RIZWAN_IDREES, ARTUR_KONCZAK).build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").excludeTerms(RIZWAN_IDREES, ARTUR_KONCZAK).build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").ascTerm().build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").ascTerm().build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").ascCount().build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).fields("authors.untouched").ascCount().build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).fields("publishedYears").descCount().build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).fields("publishedYears").descCount().build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).fields("publishedYears", "authors.untouched").ascTerm().build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).fields("publishedYears", "authors.untouched").ascTerm().build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
.withFacet(new TermFacetRequestBuilder(stringFacetName).fields("authors.untouched").ascTerm().build())
|
.withFacet(new TermFacetRequestBuilder(stringFacetName).fields("authors.untouched").ascTerm().build())
|
||||||
.build();
|
.build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||||
.withFacet(new NativeFacetRequest(FacetBuilders.termsFacet(facetName).field("publishedYears"))).build();
|
.withFacet(new NativeFacetRequest(FacetBuilders.termsFacet(facetName).field("publishedYears"))).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").regex("Art.*").build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").regex("Art.*").build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ public class ElasticsearchTemplateFacetTests {
|
|||||||
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
.withFilter(FilterBuilders.notFilter(FilterBuilders.termFilter("title", "four")))
|
||||||
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").allTerms().build()).build();
|
.withFacet(new TermFacetRequestBuilder(facetName).applyQueryFilter().fields("authors.untouched").allTerms().build()).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(3)));
|
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()
|
.to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build()
|
||||||
).build();
|
).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
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()
|
.to(YEAR_2000).range(YEAR_2000, YEAR_2002).from(YEAR_2002).build()
|
||||||
).build();
|
).build();
|
||||||
// when
|
// when
|
||||||
FacetedPage<Article> result = elasticsearchTemplate.queryForPage(searchQuery, Article.class);
|
FacetedPage<ArticleEntity> result = elasticsearchTemplate.queryForPage(searchQuery, ArticleEntity.class);
|
||||||
// then
|
// then
|
||||||
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
assertThat(result.getNumberOfElements(), is(equalTo(4)));
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.geo.GeoPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Franck Marchand
|
||||||
|
*/
|
||||||
|
@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 GeoPoint location;
|
||||||
|
|
||||||
|
private AuthorMarkerEntity(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorMarkerEntity(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 GeoPoint getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(GeoPoint location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* 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(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());
|
||||||
|
|
||||||
|
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(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 GeoBox(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"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,8 @@
|
|||||||
xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
|
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">
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
<elasticsearch:node-client id="client" local="true"
|
<elasticsearch:node-client id="client" local="true" cluster-name="testCluster" http-enabled="false" />
|
||||||
cluster-name="testCluster" http-enabled="false" />
|
|
||||||
|
<!--<elasticsearch:transport-client id="client" cluster-name="elasticsearch" cluster-nodes="127.0.1.1:9300" />-->
|
||||||
|
|
||||||
</beans>
|
</beans>
|
Loading…
x
Reference in New Issue
Block a user