Skip to content

Commit 6959c56

Browse files
christophstroblmp911de
authored andcommitted
DATAMONGO-2394 - Fix distance conversion for derived finder using near along with GeoJSON.
GeoJson requries the distance to be in meters instead of radians, so we now make sure to convert it correctly Original pull request: spring-projects#798.
1 parent b5bc432 commit 6959c56

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* @author Mark Paluch
3030
* @since 2.2
3131
*/
32-
class MetricConversion {
32+
public class MetricConversion {
3333

3434
private static final BigDecimal METERS_MULTIPLIER = new BigDecimal(Metrics.KILOMETERS.getMultiplier())
3535
.multiply(new BigDecimal(1000));
@@ -43,7 +43,7 @@ class MetricConversion {
4343
* @param metric
4444
* @return
4545
*/
46-
protected static double getMetersToMetricMultiplier(Metric metric) {
46+
public static double getMetersToMetricMultiplier(Metric metric) {
4747

4848
ConversionMultiplier conversionMultiplier = ConversionMultiplier.builder().from(METERS_MULTIPLIER).to(metric)
4949
.build();
@@ -56,7 +56,7 @@ protected static double getMetersToMetricMultiplier(Metric metric) {
5656
* @param distance
5757
* @return
5858
*/
59-
protected static double getDistanceInMeters(Distance distance) {
59+
public static double getDistanceInMeters(Distance distance) {
6060
return new BigDecimal(distance.getValue()).multiply(getMetricToMetersMultiplier(distance.getMetric()))
6161
.doubleValue();
6262
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
import org.springframework.data.mapping.PersistentPropertyPath;
3737
import org.springframework.data.mapping.PropertyPath;
3838
import org.springframework.data.mapping.context.MappingContext;
39+
import org.springframework.data.mongodb.core.geo.GeoJson;
3940
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
4041
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
4142
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
4243
import org.springframework.data.mongodb.core.query.Criteria;
4344
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
45+
import org.springframework.data.mongodb.core.query.MetricConversion;
4446
import org.springframework.data.mongodb.core.query.MongoRegexCreator;
4547
import org.springframework.data.mongodb.core.query.MongoRegexCreator.MatchMode;
4648
import org.springframework.data.mongodb.core.query.Query;
@@ -235,8 +237,14 @@ private Criteria from(Part part, MongoPersistentProperty property, Criteria crit
235237
criteria.near(pointToUse);
236238
}
237239

238-
criteria.maxDistance(it.getNormalizedValue());
239-
minDistance.ifPresent(min -> criteria.minDistance(min.getNormalizedValue()));
240+
if(pointToUse instanceof GeoJson) { // using GeoJson distance is in meters.
241+
242+
criteria.maxDistance(MetricConversion.getDistanceInMeters(it));
243+
minDistance.map(MetricConversion::getDistanceInMeters).ifPresent(min -> criteria.minDistance(min));
244+
} else {
245+
criteria.maxDistance(it.getNormalizedValue());
246+
minDistance.ifPresent(min -> criteria.minDistance(min.getNormalizedValue()));
247+
}
240248

241249
return criteria;
242250

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java

+11
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,17 @@ public void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() {
890890
assertThat(target).isEqualTo(new org.bson.Document("_id", "id-1"));
891891
}
892892

893+
@Test // DATAMONGO-2394
894+
public void leavesDistanceUntouchedWhenUsingGeoJson() {
895+
896+
Query query = query(where("geoJsonPoint").near(new GeoJsonPoint(27.987901, 86.9165379)).maxDistance(1000));
897+
898+
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
899+
context.getPersistentEntity(ClassWithGeoTypes.class));
900+
assertThat(document).containsEntry("geoJsonPoint.$near.$geometry.type", "Point");
901+
assertThat(document).containsEntry("geoJsonPoint.$near.$maxDistance", 1000.0D);
902+
}
903+
893904
@Document
894905
public class Foo {
895906
@Id private ObjectId id;

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

+11
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,17 @@ public void betweenShouldAllowSingleRageParameter() {
652652
assertThat(creator.createQuery()).isEqualTo(query(where("age").gt(10).lt(11)));
653653
}
654654

655+
@Test // DATAMONGO-2394
656+
public void nearShouldUseMetricDistanceForGeoJsonTypes() {
657+
658+
GeoJsonPoint point = new GeoJsonPoint(27.987901, 86.9165379);
659+
PartTree tree = new PartTree("findByLocationNear", User.class);
660+
MongoQueryCreator creator = new MongoQueryCreator(tree,
661+
getAccessor(converter, point, new Distance(1, Metrics.KILOMETERS)), context);
662+
663+
assertThat(creator.createQuery()).isEqualTo(query(where("location").nearSphere(point).maxDistance(1000.0D)));
664+
}
665+
655666
interface PersonRepository extends Repository<Person, Long> {
656667

657668
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);

0 commit comments

Comments
 (0)