MongoDB geospatial.

GeoJSON

{
    name: "Eiffel",
    location: { type: "Point", coordinates: [2.2945, 48.8584] },  // [lng, lat]
}

Index

db.places.createIndex({ location: "2dsphere" })

$near

db.places.find({
    location: {
        $near: {
            $geometry: { type: "Point", coordinates: [2.29, 48.85] },
            $minDistance: 0,
            $maxDistance: 5000,    // meters
        },
    },
})

Sorted by distance ASC.

$nearSphere

Similar; works with 2dsphere index over spheroid.

$geoWithin (in polygon)

db.places.find({
    location: {
        $geoWithin: {
            $geometry: {
                type: "Polygon",
                coordinates: [[
                    [2.2, 48.8], [2.4, 48.8], [2.4, 48.9], [2.2, 48.9], [2.2, 48.8],
                ]],
            },
        },
    },
})

$geoWithin: $center (circle)

$geoWithin: { $center: [[lng, lat], radiusInRadians] }
$geoWithin: { $centerSphere: [[lng, lat], radius / 6378.1] }   // km

$geoIntersects

db.regions.find({
    geometry: {
        $geoIntersects: {
            $geometry: { type: "Point", coordinates: [...] },
        },
    },
})

Find polygons containing a point.

$geoNear aggregation

db.places.aggregate([
    {
        $geoNear: {
            near: { type: "Point", coordinates: [2.29, 48.85] },
            distanceField: "dist",
            maxDistance: 5000,
            spherical: true,
        },
    },
    { $limit: 10 },
])

Must be first stage. Includes distance.

Polygon types

  • Point
  • LineString
  • Polygon
  • MultiPoint, MultiLineString, MultiPolygon
  • GeometryCollection

Closed polygon

First and last coordinates must match.

Common queries

// Within radius
{ location: { $geoWithin: { $centerSphere: [[lng, lat], 5/6378.1] } } }   // 5km

// Within bbox
{ location: { $geoWithin: { $box: [[lng1, lat1], [lng2, lat2]] } } }

Compound index

db.places.createIndex({ category: 1, location: "2dsphere" })

Faster for { category, location near }.

2d index (flat coordinates)

Older 2d index for non-spherical (game maps, etc). Use 2dsphere for real geo.

Performance

  • Use 2dsphere index.
  • $near requires the geo index in first position.
  • Polygon queries can be slow on huge collections.

Common mistakes

  • Lat/lng order: GeoJSON is [lng, lat], not [lat, lng].
  • Querying without index → COLLSCAN.
  • Polygon not closed (first != last point).
  • $near vs $geoNear (aggregation vs find).
  • maxDistance in radians vs meters confusion.

Read this next

If you want my geo patterns, they’re at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .