mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-28 14:52:20 +00:00
DATAES-89 - implements missing "near" in ElasticsearchQueryCreator
This commit is contained in:
parent
5faf54b67c
commit
6d61dceab9
@ -29,6 +29,7 @@ import org.elasticsearch.index.query.GeoDistanceFilterBuilder;
|
|||||||
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||||
|
import org.springframework.data.geo.Box;
|
||||||
import org.springframework.data.geo.Distance;
|
import org.springframework.data.geo.Distance;
|
||||||
import org.springframework.data.geo.Metrics;
|
import org.springframework.data.geo.Metrics;
|
||||||
import org.springframework.data.geo.Point;
|
import org.springframework.data.geo.Point;
|
||||||
@ -189,9 +190,17 @@ class CriteriaFilterProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
|
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
|
||||||
Assert.isTrue(value instanceof GeoBox, "single-element of boundedBy filter must be type of GeoBox");
|
Assert.isTrue(value instanceof GeoBox || value instanceof Box, "single-element of boundedBy filter must be type of GeoBox or Box");
|
||||||
GeoBox geoBBox = (GeoBox) value;
|
|
||||||
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
|
GeoBox geoBBox;
|
||||||
|
if(value instanceof Box) {
|
||||||
|
Box sdbox = (Box) value;
|
||||||
|
geoBBox = GeoBox.fromBox(sdbox);
|
||||||
|
} else {
|
||||||
|
geoBBox = (GeoBox) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
|
||||||
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
|
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core.geo;
|
package org.springframework.data.elasticsearch.core.geo;
|
||||||
|
|
||||||
|
import org.springframework.data.geo.Box;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Geo bbox used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
|
* Geo bbox used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
|
||||||
*
|
*
|
||||||
@ -37,4 +39,18 @@ public class GeoBox {
|
|||||||
public GeoPoint getBottomRight() {
|
public GeoPoint getBottomRight() {
|
||||||
return bottomRight;
|
return bottomRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return a {@link org.springframework.data.elasticsearch.core.geo.GeoBox}
|
||||||
|
* from a {@link org.springframework.data.geo.Box}.
|
||||||
|
*
|
||||||
|
* @param box {@link org.springframework.data.geo.Box} to use
|
||||||
|
* @return a {@link org.springframework.data.elasticsearch.core.geo.GeoBox}
|
||||||
|
*/
|
||||||
|
public static GeoBox fromBox(Box box) {
|
||||||
|
GeoPoint topLeft = GeoPoint.fromPoint(box.getFirst());
|
||||||
|
GeoPoint bottomRight = GeoPoint.fromPoint(box.getSecond());
|
||||||
|
|
||||||
|
return new GeoBox(topLeft, bottomRight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,6 +408,7 @@ public class Criteria {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new CriteriaEntry for bounding box created from points
|
* Creates new CriteriaEntry for bounding box created from points
|
||||||
*
|
*
|
||||||
|
@ -20,10 +20,12 @@ import java.util.Iterator;
|
|||||||
|
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||||
|
import org.springframework.data.geo.Box;
|
||||||
import org.springframework.data.geo.Distance;
|
import org.springframework.data.geo.Distance;
|
||||||
import org.springframework.data.geo.Point;
|
import org.springframework.data.geo.Point;
|
||||||
import org.springframework.data.mapping.context.MappingContext;
|
import org.springframework.data.mapping.context.MappingContext;
|
||||||
@ -38,6 +40,7 @@ import org.springframework.data.repository.query.parser.PartTree;
|
|||||||
*
|
*
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Franck Marchand
|
||||||
*/
|
*/
|
||||||
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
|
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
|
||||||
|
|
||||||
@ -134,6 +137,29 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
|
|||||||
return criteria.within((Point)firstParameter, (Distance)secondParameter);
|
return criteria.within((Point)firstParameter, (Distance)secondParameter);
|
||||||
|
|
||||||
|
|
||||||
|
if(firstParameter instanceof String && secondParameter instanceof String)
|
||||||
|
return criteria.within((String)firstParameter, (String)secondParameter);
|
||||||
|
}
|
||||||
|
case NEAR : {
|
||||||
|
Object firstParameter = parameters.next();
|
||||||
|
|
||||||
|
if(firstParameter instanceof GeoBox) {
|
||||||
|
return criteria.boundedBy((GeoBox)firstParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(firstParameter instanceof Box) {
|
||||||
|
return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
Object secondParameter = parameters.next();
|
||||||
|
|
||||||
|
// "near" query can be the same query as the "within" query
|
||||||
|
if(firstParameter instanceof GeoPoint && secondParameter instanceof String)
|
||||||
|
return criteria.within((GeoPoint)firstParameter, (String)secondParameter);
|
||||||
|
|
||||||
|
if(firstParameter instanceof Point && secondParameter instanceof Distance)
|
||||||
|
return criteria.within((Point)firstParameter, (Distance)secondParameter);
|
||||||
|
|
||||||
if(firstParameter instanceof String && secondParameter instanceof String)
|
if(firstParameter instanceof String && secondParameter instanceof String)
|
||||||
return criteria.within((String)firstParameter, (String)secondParameter);
|
return criteria.within((String)firstParameter, (String)secondParameter);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
|||||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||||
import org.springframework.data.elasticsearch.repositories.custom.SampleCustomMethodRepository;
|
import org.springframework.data.elasticsearch.repositories.custom.SampleCustomMethodRepository;
|
||||||
|
import org.springframework.data.geo.Box;
|
||||||
import org.springframework.data.geo.Distance;
|
import org.springframework.data.geo.Distance;
|
||||||
import org.springframework.data.geo.Metrics;
|
import org.springframework.data.geo.Metrics;
|
||||||
import org.springframework.data.geo.Point;
|
import org.springframework.data.geo.Point;
|
||||||
@ -42,6 +43,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||||||
/**
|
/**
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
|
* @author Franck Marchand
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration("classpath:custom-method-repository-test.xml")
|
@ContextConfiguration("classpath:custom-method-repository-test.xml")
|
||||||
@ -531,4 +533,61 @@ public class CustomMethodRepositoryTests {
|
|||||||
assertThat(page, is(notNullValue()));
|
assertThat(page, is(notNullValue()));
|
||||||
assertThat(page.getTotalElements(), is(equalTo(1L)));
|
assertThat(page.getTotalElements(), is(equalTo(1L)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldExecuteCustomMethodWithNearBox() {
|
||||||
|
// 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 sampleEntity2 = new SampleEntity();
|
||||||
|
sampleEntity2.setId(documentId);
|
||||||
|
sampleEntity2.setType("test2");
|
||||||
|
sampleEntity2.setRate(10);
|
||||||
|
sampleEntity2.setMessage("foo");
|
||||||
|
sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d));
|
||||||
|
|
||||||
|
repository.save(sampleEntity2);
|
||||||
|
|
||||||
|
// when
|
||||||
|
Page<SampleEntity> pageAll = repository.findAll(new PageRequest(0, 10));
|
||||||
|
// then
|
||||||
|
assertThat(pageAll, is(notNullValue()));
|
||||||
|
assertThat(pageAll.getTotalElements(), is(equalTo(2L)));
|
||||||
|
|
||||||
|
// when
|
||||||
|
Page<SampleEntity> page = repository.findByLocationNear(new Box(new Point(3d, 46d), new Point(4d, 45d)), new PageRequest(0, 10));
|
||||||
|
// then
|
||||||
|
assertThat(page, is(notNullValue()));
|
||||||
|
assertThat(page.getTotalElements(), is(equalTo(1L)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldExecuteCustomMethodWithNearPointAndDistance() {
|
||||||
|
// 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.findByLocationNear(new Point(3.0875d, 45.7806d), new Distance(2, Metrics.KILOMETERS), new PageRequest(0, 10));
|
||||||
|
// then
|
||||||
|
assertThat(page, is(notNullValue()));
|
||||||
|
assertThat(page.getTotalElements(), is(equalTo(1L)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,11 @@ import java.util.List;
|
|||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.elasticsearch.annotations.Query;
|
import org.springframework.data.elasticsearch.annotations.Query;
|
||||||
|
import org.springframework.data.elasticsearch.core.geo.GeoBox;
|
||||||
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
|
||||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||||
|
import org.springframework.data.geo.Box;
|
||||||
import org.springframework.data.geo.Distance;
|
import org.springframework.data.geo.Distance;
|
||||||
import org.springframework.data.geo.Point;
|
import org.springframework.data.geo.Point;
|
||||||
|
|
||||||
@ -71,4 +73,12 @@ public interface SampleCustomMethodRepository extends ElasticsearchRepository<Sa
|
|||||||
Page<SampleEntity> findByLocationWithin(GeoPoint point, String distance, 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);
|
||||||
|
|
||||||
|
Page<SampleEntity> findByLocationNear(GeoBox box, Pageable pageable);
|
||||||
|
|
||||||
|
Page<SampleEntity> findByLocationNear(Box box, Pageable pageable);
|
||||||
|
|
||||||
|
Page<SampleEntity> findByLocationNear(Point point, Distance distance, Pageable pageable);
|
||||||
|
|
||||||
|
Page<SampleEntity> findByLocationNear(GeoPoint point, String distance, Pageable pageable);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user