How to Use $geoNear in Aggregation in MongoDB
Use the
$geoNear stage as the first step in a MongoDB aggregation pipeline to find documents near a specified point. It requires a near field with coordinates and a distanceField to store calculated distances. This stage sorts documents by proximity and can filter by max distance or spherical geometry.Syntax
The $geoNear stage must be the first stage in an aggregation pipeline. It requires these main fields:
near: The point to search near, given as GeoJSON coordinates.distanceField: The field name to add the calculated distance to each document.spherical: Boolean to specify if calculations use spherical geometry (true for Earth).maxDistance(optional): Limits results to documents within this distance (in meters).query(optional): Filters documents before calculating distances.
json
{
$geoNear: {
near: { type: "Point", coordinates: [ <longitude>, <latitude> ] },
distanceField: "distance",
spherical: true,
maxDistance: <maxDistanceInMeters>,
query: { <filter> }
}
}Example
This example finds places near a given point, adds the distance in meters, and limits results to 5000 meters.
javascript
db.places.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [ -73.99279, 40.719296 ] },
distanceField: "distance",
spherical: true,
maxDistance: 5000
}
}
])Output
[
{
_id: ObjectId("..."),
name: "Coffee Shop",
location: { type: "Point", coordinates: [ -73.991, 40.720 ] },
distance: 123.45
},
{
_id: ObjectId("..."),
name: "Bookstore",
location: { type: "Point", coordinates: [ -73.993, 40.718 ] },
distance: 234.56
}
]
Common Pitfalls
- Not using
$geoNearas the first stage: It must be the first stage in the pipeline. - Missing
nearordistanceField: These are required fields. - Coordinates order: Coordinates must be in
[longitude, latitude]order. - Index requirement: The collection must have a 2dsphere index on the location field.
- Forgetting
spherical: true: Use spherical true for Earth-like calculations.
javascript
/* Wrong: $geoNear not first stage */ db.places.aggregate([ { $match: { category: "coffee" } }, { $geoNear: { near: { type: "Point", coordinates: [ -73.99279, 40.719296 ] }, distanceField: "dist", spherical: true } } ]) /* Right: $geoNear first stage */ db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.99279, 40.719296 ] }, distanceField: "dist", spherical: true, query: { category: "coffee" } } } ])
Quick Reference
| Field | Description | Required | Example |
|---|---|---|---|
| near | GeoJSON point to search near | Yes | { type: "Point", coordinates: [ -73.99279, 40.719296 ] } |
| distanceField | Field to store distance | Yes | "distance" |
| spherical | Use spherical geometry | Yes | true |
| maxDistance | Max distance in meters | No | 5000 |
| query | Filter documents before distance calc | No | { category: "coffee" } |
Key Takeaways
Always use $geoNear as the first stage in your aggregation pipeline.
Specify the 'near' point with GeoJSON coordinates in [longitude, latitude] order.
Include 'distanceField' to get the distance calculated for each document.
Ensure your collection has a 2dsphere index on the location field.
Use 'spherical: true' for accurate Earth distance calculations.