$geoNear (aggregation)
On this page
Definition
$geoNear
Outputs documents in order of nearest to farthest from a specified point.
Note
The
$geoNear
stage has the following prototype form:{ $geoNear: { <geoNear options> } } The
$geoNear
operator accepts a document that contains the following$geoNear
options. Specify all distances in the same units as those of the processed documents' coordinate system:FieldTypeDescriptiondistanceField
stringThe output field that contains the calculated distance. To specify a field within an embedded document, use dot notation.distanceMultiplier
numberOptional. The factor to multiply all distances returned by the query. For example, use thedistanceMultiplier
to convert radians, as returned by a spherical query, to kilometers by multiplying by the radius of the Earth.includeLocs
stringOptional. This specifies the output field that identifies the location used to calculate the distance. This option is useful when a location field contains multiple locations. To specify a field within an embedded document, use dot notation.key
Optional. Specify the geospatial indexed field to use when calculating the distance.
If your collection has multiple
2d
and/or multiple2dsphere
indexes, you must use thekey
option to specify the indexed field path to use. Specify Which Geospatial Index to Use provides a full example.If there is more than one
2d
index or more than one2dsphere
index and you do not specify akey
, MongoDB will return an error.If you do not specify the
key
, and you have at most only one2d
index and/or only one2dsphere
index, MongoDB looks first for a2d
index to use. If a2d
index does not exists, then MongoDB looks for a2dsphere
index to use.maxDistance
numberOptional. The maximum distance from the center point that the documents can be. MongoDB limits the results to those documents that fall within the specified distance from the center point. Starting in version 7.2, you can specify a valid constant expression that resolves to a number.
Specify the distance in meters if the specified point is GeoJSON and in radians if the specified point is legacy coordinate pairs.
minDistance
numberOptional. The minimum distance from the center point that the documents can be. MongoDB limits the results to those documents that fall outside the specified distance from the center point. Starting in version 7.2, you can specify a valid constant expression that resolves to a number.
Specify the distance in meters for GeoJSON data and in radians for legacy coordinate pairs.
near
GeoJSON point or legacy coordinate pairquery
documentOptional. Limits the results to the documents that match the query. The query syntax is the usual MongoDB read operation query syntax.
You cannot specify a
$near
predicate in thequery
field of the$geoNear
stage.spherical
booleanOptional. Determines how MongoDB calculates the distance between two points:
When
true
, MongoDB uses$nearSphere
semantics and calculates distances using spherical geometry.When
false
, MongoDB uses$near
semantics: spherical geometry for 2dsphere indexes and planar geometry for 2d indexes.
Default: false.
Behavior
Distance Calculations
$geoNear
calculates distance based on the nearest point of
the input document's perimeter.
For example, if the input document is a shape, $geoNear
identifies the point on the shape's perimeter that is nearest to the
specified point and outputs the distance between the specified point and
the shape's nearest point.
Considerations
When using $geoNear
, consider that:
You can only use
$geoNear
as the first stage of a pipeline.You must include the
distanceField
option. ThedistanceField
option specifies the field that will contain the calculated distance.$geoNear
requires a geospatial index.If you have more than one geospatial index on the collection, use the
keys
parameter to specify which field to use in the calculation. If you have only one geospatial index,$geoNear
implicitly uses the indexed field for the calculation.
You cannot specify a
$near
predicate in thequery
field of the$geoNear
stage.$geoNear
no longer has a default limit of 100 documents.Starting in MongoDB 5.1, the
near
parameter supports the let option and bound let option.Starting in MongoDB 5.3, you can use the
$geoNear
pipeline operator on any field in a time series collection.Starting in MongoDB 6.0, you can create partial and 2dsphere indexes on any field in a time series collection.
Starting in MongoDB 8.0,
$near
,$nearSphere
, and$geoNear
validate that the type of the specified GeoJSON points isPoint
. Any other input type returns an error.
Examples
Create a collection places
with the following documents:
db.places.insertMany( [ { name: "Central Park", location: { type: "Point", coordinates: [ -73.97, 40.77 ] }, category: "Parks" }, { name: "Sara D. Roosevelt Park", location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] }, category: "Parks" }, { name: "Polo Grounds", location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] }, category: "Stadiums" } ] )
The following operation creates a 2dsphere
index on the
location
field:
db.places.createIndex( { location: "2dsphere" } )
Maximum Distance
Note
The places
collection above has a 2dsphere
index.
The following aggregation uses $geoNear
to find documents
with a location at most 2 meters from the center
[ -73.99279 , 40.719296 ]
and category
equal to Parks
.
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.99279 , 40.719296 ] }, distanceField: "dist.calculated", maxDistance: 2, query: { category: "Parks" }, includeLocs: "dist.location", spherical: true } } ])
The aggregation returns the following:
{ "_id" : 8, "name" : "Sara D. Roosevelt Park", "category" : "Parks", "location" : { "type" : "Point", "coordinates" : [ -73.9928, 40.7193 ] }, "dist" : { "calculated" : 0.9539931676365992, "location" : { "type" : "Point", "coordinates" : [ -73.9928, 40.7193 ] } } }
The matching document contains two new fields:
dist.calculated
field that contains the calculated distance, anddist.location
field that contains the location used in the calculation.
Minimum Distance
Note
The following example uses the option minDistance
to specify
the minimum distance from the center point that the documents can be.
The following aggregation finds all documents with a location at least
2 meters from the center [ -73.99279 , 40.719296 ]
and category
equal to Parks
.
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.99279 , 40.719296 ] }, distanceField: "dist.calculated", minDistance: 2, query: { category: "Parks" }, includeLocs: "dist.location", spherical: true } } ])
$geoNear with the let
option
In this example:
The
let
option is used to set an array value of[-73.99279,40.719296]
to the variable$pt
.$pt
is specified as alet
option to thenear
parameter in the$geoNear
stage.
db.places.aggregate( [ { "$geoNear": { "near":"$$pt", "distanceField":"distance", "maxDistance":2, "query":{"category":"Parks"}, "includeLocs":"dist.location", "spherical":true } } ], { "let":{ "pt": [ -73.99279, 40.719296 ] } } )
The aggregation returns all documents with:
A location at most 2 meters from the point defined in the
let
variableA
category
equal toParks
.
{ _id: ObjectId("61715cf9b0c1d171bb498fd7"), name: 'Sara D. Roosevelt Park', location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] }, category: 'Parks', distance: 1.4957325341976439e-7, dist: { location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] } } }, { _id: ObjectId("61715cf9b0c1d171bb498fd6"), name: 'Central Park', location: { type: 'Point', coordinates: [ -73.97, 40.77 ] }, category: 'Parks', distance: 0.0009348548688841822, dist: { location: { type: 'Point', coordinates: [ -73.97, 40.77 ] } } }
$geoNear with Bound let
Option
The let
option can bind a variable which can be used in a
$geoNear query.
In this example, $lookup
uses:
db.places.aggregate( [ { $lookup: { from: "places", let: { pt: "$location" }, pipeline: [ { $geoNear: { near: "$$pt", distanceField: "distance" } } ], as: "joinedField" } }, { $match: { name: "Sara D. Roosevelt Park" } } ] );
The aggregation returns a document with:
The 'Sara D. Roosevelt Park' document as the main document.
Every document in the places collection as subDocuments using the
$pt
variable for calculating distance.
{ _id: ObjectId("61715cf9b0c1d171bb498fd7"), name: 'Sara D. Roosevelt Park', location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] }, category: 'Parks', joinedField: [ { _id: ObjectId("61715cf9b0c1d171bb498fd7"), name: 'Sara D. Roosevelt Park', location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] }, category: 'Parks', distance: 0 }, { _id: ObjectId("61715cf9b0c1d171bb498fd6"), name: 'Central Park', location: { type: 'Point', coordinates: [ -73.97, 40.77 ] }, category: 'Parks', distance: 5962.448255234964 }, { _id: ObjectId("61715cfab0c1d171bb498fd8"), name: 'Polo Grounds', location: { type: 'Point', coordinates: [ -73.9375, 40.8303 ] }, category: 'Stadiums', distance: 13206.535424939102 } ] }
Specify Which Geospatial Index to Use
Consider a places
collection that has a 2dsphere index on the location
field and a
2d index on the legacy
field.
A document in the places
collection resembles the following:
{ "_id" : 3, "name" : "Polo Grounds", "location": { "type" : "Point", "coordinates" : [ -73.9375, 40.8303 ] }, "legacy" : [ -73.9375, 40.8303 ], "category" : "Stadiums" }
The following example uses the key
option to specify that the
aggregation should use the location
field values for the
$geoNear
operation rather than the legacy
field values.
The pipeline also uses $limit
to return at most 5 documents.
Note
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.98142 , 40.71782 ] }, key: "location", distanceField: "dist.calculated", query: { "category": "Parks" } } }, { $limit: 5 } ])
The aggregation returns the following:
{ "_id" : 8, "name" : "Sara D. Roosevelt Park", "location" : { "type" : "Point", "coordinates" : [ -73.9928, 40.7193 ] }, "category" : "Parks", "dist" : { "calculated" : 974.175764916902 } } { "_id" : 1, "name" : "Central Park", "location" : { "type" : "Point", "coordinates" : [ -73.97, 40.77 ] }, "legacy" : [ -73.97, 40.77 ], "category" : "Parks", "dist" : { "calculated" : 5887.92792958097 } }