committed by
Mark Paluch
parent
722b6eb389
commit
5e8d752be1
@@ -27,7 +27,7 @@ import org.springframework.data.geo.Metrics;
|
||||
* {@link Metric} and {@link Distance} conversions using the metric system.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.10
|
||||
* @since 2.2
|
||||
*/
|
||||
class MetricConversion {
|
||||
|
||||
|
||||
@@ -24,14 +24,147 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Metrics;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.data.mongodb.core.geo.GeoJson;
|
||||
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Builder class to build near-queries.
|
||||
* Builder class to build near-queries. <br />
|
||||
* MongoDB {@code $geoNear} operator allows usage of a {@literal GeoJSON Point} or legacy coordinate pair. Though
|
||||
* syntactically different, there's no difference between {@code near: [-73.99171, 40.738868]} and {@code near: { type:
|
||||
* "Point", coordinates: [-73.99171, 40.738868] } } for the MongoDB server<br />
|
||||
* <br />
|
||||
* Please note that there is a huge difference in the distance calculation. Using the legacy format (for near) operates
|
||||
* upon {@literal Radians} on an Earth like sphere, whereas the {@literal GeoJSON} format uses {@literal Meters}. The
|
||||
* actual type within the document is of no concern at this point.<br />
|
||||
* To avoid a serious headache make sure to set the {@link Metric} to the desired unit of measure which ensures the
|
||||
* distance to be calculated correctly.<br />
|
||||
* <p />
|
||||
* In other words: <br />
|
||||
* Assume you've got 5 Documents like the ones below <br />
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a5"),
|
||||
* "name" : "Penn Station",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.99408, 40.75057 ] }
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a6"),
|
||||
* "name" : "10gen Office",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a9"),
|
||||
* "name" : "City Bakery ",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796aa"),
|
||||
* "name" : "Splash Bar",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796ab"),
|
||||
* "name" : "Momofuku Milk Bar",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.985839, 40.731698 ] }
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* Fetching all Documents within a 400 Meter radius from {@code [-73.99171, 40.738868] } would look like this using
|
||||
* {@literal GeoJSON}:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* {
|
||||
* $geoNear: {
|
||||
* maxDistance: 400,
|
||||
* num: 10,
|
||||
* near: { type: "Point", coordinates: [-73.99171, 40.738868] },
|
||||
* spherical:true,
|
||||
* key: "location",
|
||||
* distanceField: "distance"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* resulting in the following 3 Documents.
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a6"),
|
||||
* "name" : "10gen Office",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
|
||||
* "distance" : 0.0 // Meters
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a9"),
|
||||
* "name" : "City Bakery ",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
* "distance" : 69.3582262492474 // Meters
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796aa"),
|
||||
* "name" : "Splash Bar",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
* "distance" : 69.3582262492474 // Meters
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* Using legacy coordinate pairs one operates upon radians as discussed before. Assume we use {@link Metrics#KILOMETERS}
|
||||
* when constructing the geoNear command. The {@link Metric} will make sure the distance multiplier is set correctly, so
|
||||
* the command is rendered like
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* {
|
||||
* $geoNear: {
|
||||
* maxDistance: 0.0000627142377, // 400 Meters
|
||||
* distanceMultiplier: 6378.137,
|
||||
* num: 10,
|
||||
* near: [-73.99171, 40.738868],
|
||||
* spherical:true,
|
||||
* key: "location",
|
||||
* distanceField: "distance"
|
||||
* }
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* Please note the calculated distance now uses {@literal Kilometers} instead of {@literal Meters} as unit of measure,
|
||||
* so we need to take it times 1000 to match up to {@literal Meters} as in the {@literal GeoJSON} variant. <br />
|
||||
* Still as we've been requesting the {@link Distance} in {@link Metrics#KILOMETERS} the {@link Distance#getValue()}
|
||||
* reflects exactly this.
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a6"),
|
||||
* "name" : "10gen Office",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
|
||||
* "distance" : 0.0 // Kilometers
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796a9"),
|
||||
* "name" : "City Bakery ",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
* "distance" : 0.0693586286032982 // Kilometers
|
||||
* }
|
||||
* {
|
||||
* "_id" : ObjectId("5c10f3735d38908db52796aa"),
|
||||
* "name" : "Splash Bar",
|
||||
* "location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
* "distance" : 0.0693586286032982 // Kilometers
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
@@ -91,10 +224,14 @@ public final class NearQuery {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link NearQuery} starting at the given {@link Point}.
|
||||
* Creates a new {@link NearQuery} starting at the given {@link Point}. <br />
|
||||
* <strong>NOTE</strong> There is a difference in using {@link Point} versus {@link GeoJsonPoint}. {@link Point}
|
||||
* values are rendered as coordinate pairs in the legacy format and operate upon radians, whereas the
|
||||
* {@link GeoJsonPoint} uses according to its specification {@literal meters} as unit of measure. This may lead to
|
||||
* different results when using a {@link Metrics#NEUTRAL neutral Metric}.
|
||||
*
|
||||
* @param point must not be {@literal null}.
|
||||
* @return
|
||||
* @return new instance of {@link NearQuery}.
|
||||
*/
|
||||
public static NearQuery near(Point point) {
|
||||
return near(point, Metrics.NEUTRAL);
|
||||
@@ -103,11 +240,15 @@ public final class NearQuery {
|
||||
/**
|
||||
* Creates a {@link NearQuery} starting near the given {@link Point} using the given {@link Metric} to adapt given
|
||||
* values to further configuration. E.g. setting a {@link #maxDistance(double)} will be interpreted as a value of the
|
||||
* initially set {@link Metric}.
|
||||
* initially set {@link Metric}. <br />
|
||||
* <strong>NOTE</strong> There is a difference in using {@link Point} versus {@link GeoJsonPoint}. {@link Point}
|
||||
* values are rendered as coordinate pairs in the legacy format and operate upon radians, whereas the
|
||||
* {@link GeoJsonPoint} uses according to its specification {@literal meters} as unit of measure. This may lead to
|
||||
* different results when using a {@link Metrics#NEUTRAL neutral Metric}.
|
||||
*
|
||||
* @param point must not be {@literal null}.
|
||||
* @param metric must not be {@literal null}.
|
||||
* @return
|
||||
* @return new instance of {@link NearQuery}.
|
||||
*/
|
||||
public static NearQuery near(Point point, Metric metric) {
|
||||
return new NearQuery(point, metric);
|
||||
|
||||
@@ -23,7 +23,6 @@ import static org.springframework.data.mongodb.core.aggregation.Fields.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@@ -520,7 +519,7 @@ public class AggregationTests {
|
||||
/*
|
||||
//complex mongodb aggregation framework example from
|
||||
https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state
|
||||
|
||||
|
||||
db.zipcodes.aggregate(
|
||||
{
|
||||
$group: {
|
||||
@@ -1530,7 +1529,6 @@ public class AggregationTests {
|
||||
assertThat((Double) firstResult.get("distance"), closeTo(73.08517, 0.00001));
|
||||
}
|
||||
|
||||
|
||||
@Test // DATAMONGO-1133
|
||||
public void shouldHonorFieldAliasesForFieldReferences() {
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
@@ -56,6 +57,7 @@ import com.mongodb.client.MongoCollection;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@@ -104,6 +106,36 @@ public class GeoJsonTests {
|
||||
assertThat(result.getAverageDistance().getMetric()).isEqualTo(Metrics.KILOMETERS);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1148
|
||||
public void geoNearShouldReturnDistanceCorrectlyUsingGeoJson/*which is using the meters*/() {
|
||||
|
||||
NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73.99171, 40.738868), Metrics.KILOMETERS).num(10)
|
||||
.maxDistance(0.4);
|
||||
|
||||
GeoResults<Venue2DSphere> result = template.geoNear(geoNear, Venue2DSphere.class);
|
||||
|
||||
assertThat(result.getContent()).hasSize(3);
|
||||
assertThat(result.getAverageDistance().getMetric()).isEqualTo(Metrics.KILOMETERS);
|
||||
assertThat(result.getContent().get(0).getDistance().getValue()).isCloseTo(0.0, offset(0.000001));
|
||||
assertThat(result.getContent().get(1).getDistance().getValue()).isCloseTo(0.0693582, offset(0.000001));
|
||||
assertThat(result.getContent().get(2).getDistance().getValue()).isCloseTo(0.0693582, offset(0.000001));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1348
|
||||
public void geoNearShouldReturnDistanceCorrectly/*which is using the meters*/() {
|
||||
|
||||
NearQuery geoNear = NearQuery.near(new Point(-73.99171, 40.738868), Metrics.KILOMETERS).num(10)
|
||||
.maxDistance(0.4);
|
||||
|
||||
GeoResults<Venue2DSphere> result = template.geoNear(geoNear, Venue2DSphere.class);
|
||||
|
||||
assertThat(result.getContent()).hasSize(3);
|
||||
assertThat(result.getAverageDistance().getMetric()).isEqualTo(Metrics.KILOMETERS);
|
||||
assertThat(result.getContent().get(0).getDistance().getValue()).isCloseTo(0.0, offset(0.000001));
|
||||
assertThat(result.getContent().get(1).getDistance().getValue()).isCloseTo(0.0693582, offset(0.000001));
|
||||
assertThat(result.getContent().get(2).getDistance().getValue()).isCloseTo(0.0693582, offset(0.000001));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1135
|
||||
public void geoNearWithMiles() {
|
||||
|
||||
@@ -111,8 +143,8 @@ public class GeoJsonTests {
|
||||
|
||||
GeoResults<Venue2DSphere> result = template.geoNear(geoNear, Venue2DSphere.class);
|
||||
|
||||
assertThat(result.getContent().size(), is(not(0)));
|
||||
assertThat(result.getAverageDistance().getMetric(), is((Metric) Metrics.MILES));
|
||||
assertThat(result.getContent()).isNotEmpty();
|
||||
assertThat(result.getAverageDistance().getMetric()).isEqualTo(Metrics.MILES);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1135
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,10 +30,7 @@ import org.springframework.data.geo.Metrics;
|
||||
*/
|
||||
public class MetricConversionUnitTests {
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1348
|
||||
*/
|
||||
@Test
|
||||
@Test // DATAMONGO-1348
|
||||
public void shouldConvertMilesToMeters() {
|
||||
|
||||
Distance distance = new Distance(1, Metrics.MILES);
|
||||
@@ -42,10 +39,7 @@ public class MetricConversionUnitTests {
|
||||
assertThat(distanceInMeters, is(closeTo(1609.3438343d, 0.000000001)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1348
|
||||
*/
|
||||
@Test
|
||||
@Test // DATAMONGO-1348
|
||||
public void shouldConvertKilometersToMeters() {
|
||||
|
||||
Distance distance = new Distance(1, Metrics.KILOMETERS);
|
||||
@@ -54,10 +48,7 @@ public class MetricConversionUnitTests {
|
||||
assertThat(distanceInMeters, is(closeTo(1000, 0.000000001)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1348
|
||||
*/
|
||||
@Test
|
||||
@Test // DATAMONGO-1348
|
||||
public void shouldCalculateMetersToKilometersMultiplier() {
|
||||
|
||||
double multiplier = MetricConversion.getMetersToMetricMultiplier(Metrics.KILOMETERS);
|
||||
@@ -65,10 +56,7 @@ public class MetricConversionUnitTests {
|
||||
assertThat(multiplier, is(closeTo(0.001, 0.000000001)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1348
|
||||
*/
|
||||
@Test
|
||||
@Test // DATAMONGO-1348
|
||||
public void shouldCalculateMetersToMilesMultiplier() {
|
||||
|
||||
double multiplier = MetricConversion.getMetersToMetricMultiplier(Metrics.MILES);
|
||||
|
||||
@@ -95,8 +95,9 @@ public class NearQueryUnitTests {
|
||||
Pageable pageable = PageRequest.of(3, 5);
|
||||
NearQuery query = NearQuery.near(new Point(1, 1)).with(pageable);
|
||||
|
||||
assertThat(query.getSkip(), is((long)pageable.getPageNumber() * pageable.getPageSize()));
|
||||
assertThat((Long) query.toDocument().get("num"), is((long)(pageable.getPageNumber() + 1) * pageable.getPageSize()));
|
||||
assertThat(query.getSkip(), is((long) pageable.getPageNumber() * pageable.getPageSize()));
|
||||
assertThat((Long) query.toDocument().get("num"),
|
||||
is((long) (pageable.getPageNumber() + 1) * pageable.getPageSize()));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-445
|
||||
@@ -108,7 +109,7 @@ public class NearQueryUnitTests {
|
||||
.query(Query.query(Criteria.where("foo").is("bar")).limit(limit).skip(skip));
|
||||
|
||||
assertThat(query.getSkip(), is(skip));
|
||||
assertThat((Long) query.toDocument().get("num"), is((long)limit));
|
||||
assertThat((Long) query.toDocument().get("num"), is((long) limit));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-445
|
||||
@@ -120,8 +121,9 @@ public class NearQueryUnitTests {
|
||||
NearQuery query = NearQuery.near(new Point(1, 1))
|
||||
.query(Query.query(Criteria.where("foo").is("bar")).limit(limit).skip(skip)).with(pageable);
|
||||
|
||||
assertThat(query.getSkip(), is((long)pageable.getPageNumber() * pageable.getPageSize()));
|
||||
assertThat((Long) query.toDocument().get("num"), is((long)(pageable.getPageNumber() + 1) * pageable.getPageSize()));
|
||||
assertThat(query.getSkip(), is((long) pageable.getPageNumber() * pageable.getPageSize()));
|
||||
assertThat((Long) query.toDocument().get("num"),
|
||||
is((long) (pageable.getPageNumber() + 1) * pageable.getPageSize()));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-829
|
||||
|
||||
@@ -1435,6 +1435,177 @@ repo.findByLocationWithin( <4>
|
||||
<4> Use the legacy format `$polygon` operator.
|
||||
====
|
||||
|
||||
==== Metrics and Distance calculation
|
||||
|
||||
Then MongoDB `$geoNear` operator allows usage of a GeoJSON Point or legacy coordinate pairs.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
NearQuery.near(new Point(-73.99171, 40.738868))
|
||||
----
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"$geoNear": {
|
||||
//...
|
||||
"near": [-73.99171, 40.738868]
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
NearQuery.near(new GeoJsonPoint(-73.99171, 40.738868))
|
||||
----
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"$geoNear": {
|
||||
//...
|
||||
"near": { "type": "Point", "coordinates": [-73.99171, 40.738868] }
|
||||
}
|
||||
}
|
||||
|
||||
----
|
||||
====
|
||||
|
||||
Though syntactically different the server is fine accepting both no matter what format the target Document within the collection
|
||||
is using.
|
||||
|
||||
WARNING: There is a huge difference in the distance calculation. Using the legacy format operates
|
||||
upon _Radians_ on an Earth like sphere, whereas the GeoJSON format uses _Meters_.
|
||||
|
||||
To avoid a serious headache make sure to set the `Metric` to the desired unit of measure which ensures the
|
||||
distance to be calculated correctly.
|
||||
|
||||
In other words:
|
||||
|
||||
====
|
||||
Assume you've got 5 Documents like the ones below:
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a5"),
|
||||
"name" : "Penn Station",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.99408, 40.75057 ] }
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a6"),
|
||||
"name" : "10gen Office",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a9"),
|
||||
"name" : "City Bakery ",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796aa"),
|
||||
"name" : "Splash Bar",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796ab"),
|
||||
"name" : "Momofuku Milk Bar",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.985839, 40.731698 ] }
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Fetching all Documents within a 400 Meter radius from `[-73.99171, 40.738868]` would look like this using
|
||||
GeoJSON:
|
||||
|
||||
.GeoNear with GeoJSON
|
||||
====
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"$geoNear": {
|
||||
"maxDistance": 400, <1>
|
||||
"num": 10,
|
||||
"near": { type: "Point", coordinates: [-73.99171, 40.738868] },
|
||||
"spherical":true, <2>
|
||||
"key": "location",
|
||||
"distanceField": "distance"
|
||||
}
|
||||
}
|
||||
----
|
||||
Returning the following 3 Documents:
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a6"),
|
||||
"name" : "10gen Office",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
|
||||
"distance" : 0.0 <3>
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a9"),
|
||||
"name" : "City Bakery ",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
"distance" : 69.3582262492474 <3>
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796aa"),
|
||||
"name" : "Splash Bar",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
"distance" : 69.3582262492474 <3>
|
||||
}
|
||||
----
|
||||
<1> Maximum distance from center point in _Meters_.
|
||||
<2> GeoJSON always operates upon a sphere.
|
||||
<3> Distance from center point in _Meters_.
|
||||
====
|
||||
|
||||
Now, when using legacy coordinate pairs one operates upon _Radians_ as discussed before. So we use `Metrics#KILOMETERS
|
||||
when constructing the `$geoNear` command. The `Metric` makes sure the distance multiplier is set correctly.
|
||||
|
||||
.GeoNear with Legacy Coordinate Pairs
|
||||
====
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"$geoNear": {
|
||||
"maxDistance": 0.0000627142377, <1>
|
||||
"distanceMultiplier": 6378.137, <2>
|
||||
"num": 10,
|
||||
"near": [-73.99171, 40.738868],
|
||||
"spherical":true, <3>
|
||||
"key": "location",
|
||||
"distanceField": "distance"
|
||||
}
|
||||
}
|
||||
----
|
||||
Returning the 3 Documents just like the GeoJSON variant:
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a6"),
|
||||
"name" : "10gen Office",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.99171, 40.738868 ] }
|
||||
"distance" : 0.0 <4>
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796a9"),
|
||||
"name" : "City Bakery ",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
"distance" : 0.0693586286032982 <4>
|
||||
}
|
||||
{
|
||||
"_id" : ObjectId("5c10f3735d38908db52796aa"),
|
||||
"name" : "Splash Bar",
|
||||
"location" : { "type" : "Point", "coordinates" : [ -73.992491, 40.738673 ] }
|
||||
"distance" : 0.0693586286032982 <4>
|
||||
}
|
||||
----
|
||||
<1> Maximum distance from center point in _Radians_.
|
||||
<2> The distance multiplier so we get _Kilometers_ as resulting distance.
|
||||
<3> Make sure we operate on a 2d_sphere index.
|
||||
<4> Distance from center point in _Kilometers_ - take it times 1000 to match _Meters_ of the GeoJSON variant.
|
||||
====
|
||||
|
||||
[[mongo.textsearch]]
|
||||
=== Full-text Queries
|
||||
|
||||
|
||||
Reference in New Issue
Block a user