DATAES-129 : Custom Repository Method for simple geo request does not work

This commit is contained in:
Franck MARCHAND 2014-09-13 00:43:24 +02:00 committed by Mohsin Husen
parent 7cf7cb9168
commit bb62148bb7
5 changed files with 80 additions and 14 deletions

View File

@ -24,10 +24,10 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils; import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.BoostableQueryBuilder; import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.elasticsearch.core.query.Criteria; import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.geo.Point;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -118,9 +118,9 @@ class CriteriaQueryProcessor {
} }
QueryBuilder query = null; QueryBuilder query = null;
String searchText = StringUtils.toString(value); String searchText = StringUtils.toString(value);
switch (key) { switch (key) {
case EQUALS: case EQUALS:
query = queryString(searchText).field(fieldName); query = queryString(searchText).field(fieldName);
break; break;

View File

@ -193,7 +193,7 @@ public class Criteria {
* @return * @return
*/ */
public Criteria is(Object o) { public Criteria is(Object o) {
queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o)); queryCriteria.add(new CriteriaEntry(OperationKey.EQUALS, o));
return this; return this;
} }

View File

@ -61,7 +61,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
protected CriteriaQuery create(Part part, Iterator<Object> iterator) { protected CriteriaQuery create(Part part, Iterator<Object> iterator) {
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context PersistentPropertyPath<ElasticsearchPersistentProperty> path = context
.getPersistentPropertyPath(part.getProperty()); .getPersistentPropertyPath(part.getProperty());
return new CriteriaQuery(from(part.getType(), return new CriteriaQuery(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator));
} }
@ -72,7 +72,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
} }
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context PersistentPropertyPath<ElasticsearchPersistentProperty> path = context
.getPersistentPropertyPath(part.getProperty()); .getPersistentPropertyPath(part.getProperty());
return base.addCriteria(from(part.getType(), return base.addCriteria(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator)); new Criteria(path.toDotPath(ElasticsearchPersistentProperty.PropertyToFieldNameConverter.INSTANCE)), iterator));
} }
@ -89,7 +89,9 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return query.addSort(sort); return query.addSort(sort);
} }
private Criteria from(Part.Type type, Criteria instance, Iterator<?> parameters) { private Criteria from(Part part, Criteria instance, Iterator<?> parameters) {
Part.Type type = part.getType();
Criteria criteria = instance; Criteria criteria = instance;
if (criteria == null) { if (criteria == null) {
criteria = new Criteria(); criteria = new Criteria();
@ -99,8 +101,6 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.is(true); return criteria.is(true);
case FALSE: case FALSE:
return criteria.is(false); return criteria.is(false);
case SIMPLE_PROPERTY:
return criteria.is(parameters.next());
case NEGATING_SIMPLE_PROPERTY: case NEGATING_SIMPLE_PROPERTY:
return criteria.is(parameters.next()).not(); return criteria.is(parameters.next()).not();
case REGEX: case REGEX:
@ -126,11 +126,24 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.in(asArray(parameters.next())); return criteria.in(asArray(parameters.next()));
case NOT_IN: case NOT_IN:
return criteria.in(asArray(parameters.next())).not(); return criteria.in(asArray(parameters.next())).not();
case SIMPLE_PROPERTY:
case WITHIN: { case WITHIN: {
Object firstParameter = parameters.next(); Object firstParameter = parameters.next();
Object secondParameter = parameters.next(); Object secondParameter = null;
if(type == Part.Type.SIMPLE_PROPERTY) {
if(part.getProperty().getType() != GeoPoint.class)
return criteria.is(firstParameter);
else {
// it means it's a simple find with exact geopoint matching (e.g. findByLocation)
// and because Elasticsearch does not have any kind of query with just a geopoint
// as argument we use a "geo distance" query with a distance of one meter.
secondParameter = ".001km";
}
} else {
secondParameter = parameters.next();
}
if (firstParameter instanceof GeoPoint && secondParameter instanceof String) if (firstParameter instanceof GeoPoint && secondParameter instanceof String)
return criteria.within((GeoPoint) firstParameter, (String) secondParameter); return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance) if (firstParameter instanceof Point && secondParameter instanceof Distance)

View File

@ -495,6 +495,55 @@ public class CustomMethodRepositoryTests {
assertThat(sampleEntities.size(), is(1)); assertThat(sampleEntities.size(), is(1));
} }
@Test
public void shouldExecuteCustomMethodWithGeoPoint() {
// given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId);
sampleEntity.setType("test");
sampleEntity.setRate(10);
sampleEntity.setMessage("foo");
sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d));
repository.save(sampleEntity);
// when
Page<SampleEntity> page = repository.findByLocation(new GeoPoint(45.7806d, 3.0875d), new PageRequest(0, 10));
// then
assertThat(page, is(notNullValue()));
assertThat(page.getTotalElements(), is(equalTo(1L)));
}
@Test
public void shouldExecuteCustomMethodWithGeoPointAndString() {
// given
String documentId = randomNumeric(5);
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId);
sampleEntity.setType("test");
sampleEntity.setRate(10);
sampleEntity.setMessage("foo");
sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d));
repository.save(sampleEntity);
documentId = randomNumeric(5);
sampleEntity = new SampleEntity();
sampleEntity.setId(documentId);
sampleEntity.setType("test");
sampleEntity.setRate(10);
sampleEntity.setMessage("foo");
sampleEntity.setLocation(new GeoPoint(48.7806d, 3.0875d));
repository.save(sampleEntity);
// when
Page<SampleEntity> page = repository.findByLocationAndMessage(new GeoPoint(45.7806d, 3.0875d), "foo", new PageRequest(0, 10));
// then
assertThat(page, is(notNullValue()));
assertThat(page.getTotalElements(), is(equalTo(1L)));
}
@Test @Test
public void shouldExecuteCustomMethodWithWithinGeoPoint() { public void shouldExecuteCustomMethodWithWithinGeoPoint() {
// given // given

View File

@ -71,7 +71,11 @@ public interface SampleCustomMethodRepository extends ElasticsearchRepository<Sa
Page<SampleEntity> findByMessageOrderByTypeAsc(String message, Pageable pageable); Page<SampleEntity> findByMessageOrderByTypeAsc(String message, Pageable pageable);
Page<SampleEntity> findByLocationWithin(GeoPoint point, String distance, Pageable pageable); Page<SampleEntity> findByLocation(GeoPoint point, Pageable pageable);
Page<SampleEntity> findByLocationAndMessage(GeoPoint point, String msg, Pageable pageable);
Page<SampleEntity> findByLocationWithin(GeoPoint point, String distance, Pageable pageable);
Page<SampleEntity> findByLocationWithin(Point point, Distance distance, Pageable pageable); Page<SampleEntity> findByLocationWithin(Point point, Distance distance, Pageable pageable);