Browse Source

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: #798.
pull/814/head
Christoph Strobl 6 years ago committed by Mark Paluch
parent
commit
c28ace6d40
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MetricConversion.java
  2. 12
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java
  3. 11
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java
  4. 11
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

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

@ -29,7 +29,7 @@ import org.springframework.data.geo.Metrics; @@ -29,7 +29,7 @@ import org.springframework.data.geo.Metrics;
* @author Mark Paluch
* @since 2.2
*/
class MetricConversion {
public class MetricConversion {
private static final BigDecimal METERS_MULTIPLIER = new BigDecimal(Metrics.KILOMETERS.getMultiplier())
.multiply(new BigDecimal(1000));
@ -43,7 +43,7 @@ class MetricConversion { @@ -43,7 +43,7 @@ class MetricConversion {
* @param metric
* @return
*/
protected static double getMetersToMetricMultiplier(Metric metric) {
public static double getMetersToMetricMultiplier(Metric metric) {
ConversionMultiplier conversionMultiplier = ConversionMultiplier.builder().from(METERS_MULTIPLIER).to(metric)
.build();
@ -56,7 +56,7 @@ class MetricConversion { @@ -56,7 +56,7 @@ class MetricConversion {
* @param distance
* @return
*/
protected static double getDistanceInMeters(Distance distance) {
public static double getDistanceInMeters(Distance distance) {
return new BigDecimal(distance.getValue()).multiply(getMetricToMetersMultiplier(distance.getMetric()))
.doubleValue();
}

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

@ -36,11 +36,13 @@ import org.springframework.data.geo.Shape; @@ -36,11 +36,13 @@ import org.springframework.data.geo.Shape;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.geo.GeoJson;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.data.mongodb.core.query.MetricConversion;
import org.springframework.data.mongodb.core.query.MongoRegexCreator;
import org.springframework.data.mongodb.core.query.MongoRegexCreator.MatchMode;
import org.springframework.data.mongodb.core.query.Query;
@ -235,8 +237,14 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> { @@ -235,8 +237,14 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
criteria.near(pointToUse);
}
criteria.maxDistance(it.getNormalizedValue());
minDistance.ifPresent(min -> criteria.minDistance(min.getNormalizedValue()));
if(pointToUse instanceof GeoJson) { // using GeoJson distance is in meters.
criteria.maxDistance(MetricConversion.getDistanceInMeters(it));
minDistance.map(MetricConversion::getDistanceInMeters).ifPresent(min -> criteria.minDistance(min));
} else {
criteria.maxDistance(it.getNormalizedValue());
minDistance.ifPresent(min -> criteria.minDistance(min.getNormalizedValue()));
}
return criteria;

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

@ -890,6 +890,17 @@ public class QueryMapperUnitTests { @@ -890,6 +890,17 @@ public class QueryMapperUnitTests {
assertThat(target).isEqualTo(new org.bson.Document("_id", "id-1"));
}
@Test // DATAMONGO-2394
public void leavesDistanceUntouchedWhenUsingGeoJson() {
Query query = query(where("geoJsonPoint").near(new GeoJsonPoint(27.987901, 86.9165379)).maxDistance(1000));
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
context.getPersistentEntity(ClassWithGeoTypes.class));
assertThat(document).containsEntry("geoJsonPoint.$near.$geometry.type", "Point");
assertThat(document).containsEntry("geoJsonPoint.$near.$maxDistance", 1000.0D);
}
@Document
public class Foo {
@Id private ObjectId id;

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

@ -652,6 +652,17 @@ public class MongoQueryCreatorUnitTests { @@ -652,6 +652,17 @@ public class MongoQueryCreatorUnitTests {
assertThat(creator.createQuery()).isEqualTo(query(where("age").gt(10).lt(11)));
}
@Test // DATAMONGO-2394
public void nearShouldUseMetricDistanceForGeoJsonTypes() {
GeoJsonPoint point = new GeoJsonPoint(27.987901, 86.9165379);
PartTree tree = new PartTree("findByLocationNear", User.class);
MongoQueryCreator creator = new MongoQueryCreator(tree,
getAccessor(converter, point, new Distance(1, Metrics.KILOMETERS)), context);
assertThat(creator.createQuery()).isEqualTo(query(where("location").nearSphere(point).maxDistance(1000.0D)));
}
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);

Loading…
Cancel
Save