From 6d61dceab920a5ba29eebb1f8c928640d30625a5 Mon Sep 17 00:00:00 2001 From: Franck MARCHAND Date: Mon, 9 Jun 2014 23:22:51 +0200 Subject: [PATCH] DATAES-89 - implements missing "near" in ElasticsearchQueryCreator --- .../core/CriteriaFilterProcessor.java | 15 ++++- .../data/elasticsearch/core/geo/GeoBox.java | 16 +++++ .../elasticsearch/core/query/Criteria.java | 1 + .../parser/ElasticsearchQueryCreator.java | 26 ++++++++ .../CustomMethodRepositoryTests.java | 59 +++++++++++++++++++ .../custom/SampleCustomMethodRepository.java | 10 ++++ 6 files changed, 124 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/CriteriaFilterProcessor.java b/src/main/java/org/springframework/data/elasticsearch/core/CriteriaFilterProcessor.java index d02763f1f..b138ea3c1 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/CriteriaFilterProcessor.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/CriteriaFilterProcessor.java @@ -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.GeoPoint; 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.Metrics; import org.springframework.data.geo.Point; @@ -189,9 +190,17 @@ class CriteriaFilterProcessor { } private void oneParameterBBox(GeoBoundingBoxFilterBuilder filter, Object value) { - Assert.isTrue(value instanceof GeoBox, "single-element of boundedBy filter must be type of GeoBox"); - GeoBox geoBBox = (GeoBox) value; - filter.topLeft(geoBBox.getTopLeft().getLat(), geoBBox.getTopLeft().getLon()); + Assert.isTrue(value instanceof GeoBox || value instanceof Box, "single-element of boundedBy filter must be type of GeoBox or Box"); + + 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()); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/geo/GeoBox.java b/src/main/java/org/springframework/data/elasticsearch/core/geo/GeoBox.java index 691ade147..bb4e5d526 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/geo/GeoBox.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/geo/GeoBox.java @@ -15,6 +15,8 @@ */ 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}. * @@ -37,4 +39,18 @@ public class GeoBox { public GeoPoint getBottomRight() { 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); + } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java b/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java index d4f1bcec3..5980eb6cf 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/Criteria.java @@ -408,6 +408,7 @@ public class Criteria { } + /** * Creates new CriteriaEntry for bounding box created from points * diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java b/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java index 97c1955ba..db12425d4 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/query/parser/ElasticsearchQueryCreator.java @@ -20,10 +20,12 @@ import java.util.Iterator; import org.springframework.dao.InvalidDataAccessApiUsageException; 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.mapping.ElasticsearchPersistentProperty; import org.springframework.data.elasticsearch.core.query.Criteria; 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.Point; import org.springframework.data.mapping.context.MappingContext; @@ -38,6 +40,7 @@ import org.springframework.data.repository.query.parser.PartTree; * * @author Rizwan Idrees * @author Mohsin Husen + * @author Franck Marchand */ public class ElasticsearchQueryCreator extends AbstractQueryCreator { @@ -134,6 +137,29 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator pageAll = repository.findAll(new PageRequest(0, 10)); + // then + assertThat(pageAll, is(notNullValue())); + assertThat(pageAll.getTotalElements(), is(equalTo(2L))); + + // when + Page 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 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))); + } } + diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java b/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java index a7ca3856a..d68f7b8b0 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/custom/SampleCustomMethodRepository.java @@ -20,9 +20,11 @@ import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; 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.entities.SampleEntity; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import org.springframework.data.geo.Box; import org.springframework.data.geo.Distance; import org.springframework.data.geo.Point; @@ -71,4 +73,12 @@ public interface SampleCustomMethodRepository extends ElasticsearchRepository findByLocationWithin(GeoPoint point, String distance, Pageable pageable); Page findByLocationWithin(Point point, Distance distance, Pageable pageable); + + Page findByLocationNear(GeoBox box, Pageable pageable); + + Page findByLocationNear(Box box, Pageable pageable); + + Page findByLocationNear(Point point, Distance distance, Pageable pageable); + + Page findByLocationNear(GeoPoint point, String distance, Pageable pageable); }