Skip to content

Commit 6d61dce

Browse files
committed
DATAES-89 - implements missing "near" in ElasticsearchQueryCreator
1 parent 5faf54b commit 6d61dce

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed

src/main/java/org/springframework/data/elasticsearch/core/CriteriaFilterProcessor.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.data.elasticsearch.core.geo.GeoBox;
3030
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
3131
import org.springframework.data.elasticsearch.core.query.Criteria;
32+
import org.springframework.data.geo.Box;
3233
import org.springframework.data.geo.Distance;
3334
import org.springframework.data.geo.Metrics;
3435
import org.springframework.data.geo.Point;
@@ -189,9 +190,17 @@ private void extractDistanceString(Distance distance, StringBuilder sb) {
189190
}
190191

191192
private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) {
192-
Assert.isTrue(value instanceof GeoBox, "single-element of boundedBy filter must be type of GeoBox");
193-
GeoBox geoBBox = (GeoBox) value;
194-
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
193+
Assert.isTrue(value instanceof GeoBox || value instanceof Box, "single-element of boundedBy filter must be type of GeoBox or Box");
194+
195+
GeoBox geoBBox;
196+
if(value instanceof Box) {
197+
Box sdbox = (Box) value;
198+
geoBBox = GeoBox.fromBox(sdbox);
199+
} else {
200+
geoBBox = (GeoBox) value;
201+
}
202+
203+
filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon());
195204
filter.bottomRight(geoBBox.getBottomRight().getLat(), geoBBox.getBottomRight().getLon());
196205
}
197206

src/main/java/org/springframework/data/elasticsearch/core/geo/GeoBox.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.elasticsearch.core.geo;
1717

18+
import org.springframework.data.geo.Box;
19+
1820
/**
1921
* Geo bbox used for #{@link org.springframework.data.elasticsearch.core.query.Criteria}.
2022
*
@@ -37,4 +39,18 @@ public GeoPoint getTopLeft() {
3739
public GeoPoint getBottomRight() {
3840
return bottomRight;
3941
}
42+
43+
/**
44+
* return a {@link org.springframework.data.elasticsearch.core.geo.GeoBox}
45+
* from a {@link org.springframework.data.geo.Box}.
46+
*
47+
* @param box {@link org.springframework.data.geo.Box} to use
48+
* @return a {@link org.springframework.data.elasticsearch.core.geo.GeoBox}
49+
*/
50+
public static GeoBox fromBox(Box box) {
51+
GeoPoint topLeft = GeoPoint.fromPoint(box.getFirst());
52+
GeoPoint bottomRight = GeoPoint.fromPoint(box.getSecond());
53+
54+
return new GeoBox(topLeft, bottomRight);
55+
}
4056
}

src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ public Criteria boundedBy(GeoBox boundingBox) {
408408
}
409409

410410

411+
411412
/**
412413
* Creates new CriteriaEntry for bounding box created from points
413414
*

src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020

2121
import org.springframework.dao.InvalidDataAccessApiUsageException;
2222
import org.springframework.data.domain.Sort;
23+
import org.springframework.data.elasticsearch.core.geo.GeoBox;
2324
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
2425
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
2526
import org.springframework.data.elasticsearch.core.query.Criteria;
2627
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
28+
import org.springframework.data.geo.Box;
2729
import org.springframework.data.geo.Distance;
2830
import org.springframework.data.geo.Point;
2931
import org.springframework.data.mapping.context.MappingContext;
@@ -38,6 +40,7 @@
3840
*
3941
* @author Rizwan Idrees
4042
* @author Mohsin Husen
43+
* @author Franck Marchand
4144
*/
4245
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
4346

@@ -134,6 +137,29 @@ private Criteria from(Part.Type type, Criteria instance, Iterator<?> parameters)
134137
return criteria.within((Point)firstParameter, (Distance)secondParameter);
135138

136139

140+
if(firstParameter instanceof String && secondParameter instanceof String)
141+
return criteria.within((String)firstParameter, (String)secondParameter);
142+
}
143+
case NEAR : {
144+
Object firstParameter = parameters.next();
145+
146+
if(firstParameter instanceof GeoBox) {
147+
return criteria.boundedBy((GeoBox)firstParameter);
148+
}
149+
150+
if(firstParameter instanceof Box) {
151+
return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter));
152+
}
153+
154+
Object secondParameter = parameters.next();
155+
156+
// "near" query can be the same query as the "within" query
157+
if(firstParameter instanceof GeoPoint && secondParameter instanceof String)
158+
return criteria.within((GeoPoint)firstParameter, (String)secondParameter);
159+
160+
if(firstParameter instanceof Point && secondParameter instanceof Distance)
161+
return criteria.within((Point)firstParameter, (Distance)secondParameter);
162+
137163
if(firstParameter instanceof String && secondParameter instanceof String)
138164
return criteria.within((String)firstParameter, (String)secondParameter);
139165
}

src/test/java/org/springframework/data/elasticsearch/repositories/CustomMethodRepositoryTests.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
3434
import org.springframework.data.elasticsearch.entities.SampleEntity;
3535
import org.springframework.data.elasticsearch.repositories.custom.SampleCustomMethodRepository;
36+
import org.springframework.data.geo.Box;
3637
import org.springframework.data.geo.Distance;
3738
import org.springframework.data.geo.Metrics;
3839
import org.springframework.data.geo.Point;
@@ -42,6 +43,7 @@
4243
/**
4344
* @author Rizwan Idrees
4445
* @author Mohsin Husen
46+
* @author Franck Marchand
4547
*/
4648
@RunWith(SpringJUnit4ClassRunner.class)
4749
@ContextConfiguration("classpath:custom-method-repository-test.xml")
@@ -531,4 +533,61 @@ public void shouldExecuteCustomMethodWithWithinPoint() {
531533
assertThat(page, is(notNullValue()));
532534
assertThat(page.getTotalElements(), is(equalTo(1L)));
533535
}
536+
537+
@Test
538+
public void shouldExecuteCustomMethodWithNearBox() {
539+
// given
540+
String documentId = randomNumeric(5);
541+
SampleEntity sampleEntity = new SampleEntity();
542+
sampleEntity.setId(documentId);
543+
sampleEntity.setType("test");
544+
sampleEntity.setRate(10);
545+
sampleEntity.setMessage("foo");
546+
sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d));
547+
548+
repository.save(sampleEntity);
549+
550+
documentId = randomNumeric(5);
551+
SampleEntity sampleEntity2 = new SampleEntity();
552+
sampleEntity2.setId(documentId);
553+
sampleEntity2.setType("test2");
554+
sampleEntity2.setRate(10);
555+
sampleEntity2.setMessage("foo");
556+
sampleEntity2.setLocation(new GeoPoint(30.7806d, 0.0875d));
557+
558+
repository.save(sampleEntity2);
559+
560+
// when
561+
Page<SampleEntity> pageAll = repository.findAll(new PageRequest(0, 10));
562+
// then
563+
assertThat(pageAll, is(notNullValue()));
564+
assertThat(pageAll.getTotalElements(), is(equalTo(2L)));
565+
566+
// when
567+
Page<SampleEntity> page = repository.findByLocationNear(new Box(new Point(3d, 46d), new Point(4d, 45d)), new PageRequest(0, 10));
568+
// then
569+
assertThat(page, is(notNullValue()));
570+
assertThat(page.getTotalElements(), is(equalTo(1L)));
571+
}
572+
573+
@Test
574+
public void shouldExecuteCustomMethodWithNearPointAndDistance() {
575+
// given
576+
String documentId = randomNumeric(5);
577+
SampleEntity sampleEntity = new SampleEntity();
578+
sampleEntity.setId(documentId);
579+
sampleEntity.setType("test");
580+
sampleEntity.setRate(10);
581+
sampleEntity.setMessage("foo");
582+
sampleEntity.setLocation(new GeoPoint(45.7806d, 3.0875d));
583+
584+
repository.save(sampleEntity);
585+
586+
// when
587+
Page<SampleEntity> page = repository.findByLocationNear(new Point(3.0875d, 45.7806d), new Distance(2, Metrics.KILOMETERS), new PageRequest(0, 10));
588+
// then
589+
assertThat(page, is(notNullValue()));
590+
assertThat(page.getTotalElements(), is(equalTo(1L)));
591+
}
534592
}
593+

src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
import org.springframework.data.domain.Page;
2121
import org.springframework.data.domain.Pageable;
2222
import org.springframework.data.elasticsearch.annotations.Query;
23+
import org.springframework.data.elasticsearch.core.geo.GeoBox;
2324
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
2425
import org.springframework.data.elasticsearch.entities.SampleEntity;
2526
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
27+
import org.springframework.data.geo.Box;
2628
import org.springframework.data.geo.Distance;
2729
import org.springframework.data.geo.Point;
2830

@@ -71,4 +73,12 @@ public interface SampleCustomMethodRepository extends ElasticsearchRepository<Sa
7173
Page<SampleEntity> findByLocationWithin(GeoPoint point, String distance, Pageable pageable);
7274

7375
Page<SampleEntity> findByLocationWithin(Point point, Distance distance, Pageable pageable);
76+
77+
Page<SampleEntity> findByLocationNear(GeoBox box, Pageable pageable);
78+
79+
Page<SampleEntity> findByLocationNear(Box box, Pageable pageable);
80+
81+
Page<SampleEntity> findByLocationNear(Point point, Distance distance, Pageable pageable);
82+
83+
Page<SampleEntity> findByLocationNear(GeoPoint point, String distance, Pageable pageable);
7484
}

0 commit comments

Comments
 (0)