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.
This commit is contained in:
committed by
Mark Paluch
parent
b5bc4320aa
commit
6959c56df6
@@ -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 {
|
||||
* @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 {
|
||||
* @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();
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user