0
0
MongodbHow-ToBeginner · 4 min read

How to Use $geoWithin in MongoDB for Geospatial Queries

Use the $geoWithin operator in MongoDB to find documents where a geospatial field is inside a specified shape like a polygon or circle. It works with GeoJSON objects or legacy coordinate pairs inside a $geoWithin query to filter locations within boundaries.
📐

Syntax

The $geoWithin operator is used inside a find() query to filter documents with geospatial data inside a specified shape.

Basic syntax:

  • { locationField: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [...] } } } } - Finds documents where locationField is inside the polygon.
  • { locationField: { $geoWithin: { $centerSphere: [ [lng, lat], radiusInRadians ] } } } - Finds documents inside a circle defined by center and radius.

The locationField must be indexed with a 2dsphere index for GeoJSON data.

mongodb
db.places.find({
  location: {
    $geoWithin: {
      $geometry: {
        type: "Polygon",
        coordinates: [
          [
            [ -73.97, 40.77 ],
            [ -73.88, 40.78 ],
            [ -73.88, 40.68 ],
            [ -73.97, 40.68 ],
            [ -73.97, 40.77 ]
          ]
        ]
      }
    }
  }
})
💻

Example

This example shows how to find places inside a polygon area using $geoWithin. The location field stores GeoJSON points.

mongodb
use testdb

// Create collection and add 2dsphere index
db.places.createIndex({ location: "2dsphere" })

// Insert sample documents
db.places.insertMany([
  { name: "Park", location: { type: "Point", coordinates: [ -73.95, 40.75 ] } },
  { name: "Museum", location: { type: "Point", coordinates: [ -73.99, 40.76 ] } },
  { name: "Cafe", location: { type: "Point", coordinates: [ -73.87, 40.70 ] } }
])

// Query places within polygon
const results = db.places.find({
  location: {
    $geoWithin: {
      $geometry: {
        type: "Polygon",
        coordinates: [[
          [ -73.97, 40.77 ],
          [ -73.88, 40.78 ],
          [ -73.88, 40.68 ],
          [ -73.97, 40.68 ],
          [ -73.97, 40.77 ]
        ]]
      }
    }
  }
}).toArray()

printjson(results)
Output
[ { "_id": ObjectId("..."), "name": "Park", "location": { "type": "Point", "coordinates": [ -73.95, 40.75 ] } }, { "_id": ObjectId("..."), "name": "Cafe", "location": { "type": "Point", "coordinates": [ -73.87, 40.70 ] } } ]
⚠️

Common Pitfalls

  • Missing 2dsphere index: The $geoWithin query requires a 2dsphere index on the location field; otherwise, it will fail or be slow.
  • Incorrect coordinate order: GeoJSON uses [longitude, latitude] order, not latitude then longitude.
  • Shape closure: Polygons must have the first and last coordinate points identical to close the shape.
  • Using legacy coordinate pairs with GeoJSON: Mixing legacy coordinate pairs and GeoJSON formats can cause errors.
mongodb
/* Wrong: Missing 2dsphere index */
db.places.find({
  location: {
    $geoWithin: {
      $geometry: {
        type: "Polygon",
        coordinates: [[
          [ -73.97, 40.77 ],
          [ -73.88, 40.78 ],
          [ -73.88, 40.68 ],
          [ -73.97, 40.68 ],
          [ -73.97, 40.77 ]
        ]]
      }
    }
  }
})

/* Right: Create 2dsphere index first */
db.places.createIndex({ location: "2dsphere" })
📊

Quick Reference

  • $geoWithin: Finds documents with locations inside a geometry.
  • $geometry: Defines GeoJSON shape (Polygon, MultiPolygon, etc.).
  • $centerSphere: Defines a circle with center and radius in radians.
  • Always use 2dsphere index on geospatial fields.
  • Coordinates order is [longitude, latitude].

Key Takeaways

Use $geoWithin to find documents with locations inside a specified GeoJSON shape.
Always create a 2dsphere index on the geospatial field before querying with $geoWithin.
Coordinates in GeoJSON must be in [longitude, latitude] order.
Polygons must be closed by repeating the first coordinate at the end.
Use $geometry for polygons and $centerSphere for circular areas in $geoWithin queries.