MongoDB Geospatial Queries

Many applications ask questions about location. Which restaurants sit within two kilometers of me? Which delivery zone covers this address? MongoDB answers these questions with geospatial queries, which store places as coordinates and search them by distance and area.

The Map Pin Picture

Each place in the database acts like a pin on a map. A geospatial query draws a circle or shape on the map and returns every pin inside it.

            North
              ^
      .  Cafe |        . Library
              |   (  *  )          * = you
  . Park      |  (  Shop )         ( ) = search circle, 2 km radius
              |   (     )
 West <-------+---------------> East
              |      . Hotel
              v
            South

The Shop sits inside the circle and appears in the results. The other places lie outside and stay hidden.

Store Locations with GeoJSON

MongoDB stores locations in the GeoJSON format. A point holds a type and a list of two numbers. The list puts longitude first and latitude second. Many beginners reverse the order, so check it every time.

db.places.insertMany([
  { name: "Central Cafe",  location: { type: "Point", coordinates: [73.8567, 18.5204] } },
  { name: "City Library",  location: { type: "Point", coordinates: [73.8700, 18.5300] } },
  { name: "Hill Park",     location: { type: "Point", coordinates: [73.9100, 18.5600] } }
])

Coordinate Rules

  • Longitude ranges from -180 to 180.
  • Latitude ranges from -90 to 90.
  • Write longitude first: [longitude, latitude].

Create a Geospatial Index

The 2dsphere index prepares location data for fast searching on a globe-shaped Earth:

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

The $near and $geoNear features need this index, and the other location queries run much faster with it.

Find Nearby Places with $near

The $near operator returns documents sorted from closest to farthest. Distances use meters:

db.places.find({
  location: {
    $near: {
      $geometry: { type: "Point", coordinates: [73.8600, 18.5250] },
      $maxDistance: 3000,
      $minDistance: 0
    }
  }
})

The query returns every place within 3,000 meters of the given point, nearest first. Leave out $maxDistance to sort every place by distance.

Search Inside an Area with $geoWithin

The $geoWithin operator finds places inside a shape. Results come back unsorted.

Circle

The $centerSphere shape takes a center point and a radius in radians. Divide the distance in kilometers by 6378.1 to convert it:

db.places.find({
  location: {
    $geoWithin: { $centerSphere: [ [73.8600, 18.5250], 5 / 6378.1 ] }
  }
})

The radius 5 / 6378.1 equals a 5 kilometer circle.

Polygon

A polygon describes a custom area, such as a delivery zone. The first and last coordinates must match to close the shape:

db.places.find({
  location: {
    $geoWithin: {
      $geometry: {
        type: "Polygon",
        coordinates: [[
          [73.80, 18.50], [73.90, 18.50], [73.90, 18.55], [73.80, 18.55], [73.80, 18.50]
        ]]
      }
    }
  }
})

Find Overlapping Shapes with $geoIntersects

Store areas as polygons, such as delivery zones, and ask which zone contains a customer location:

db.zones.find({
  area: {
    $geoIntersects: {
      $geometry: { type: "Point", coordinates: [73.8600, 18.5250] }
    }
  }
})

Show Distances with the $geoNear Stage

The aggregation stage $geoNear calculates the distance to each place and writes it into a new field:

db.places.aggregate([
  {
    $geoNear: {
      near: { type: "Point", coordinates: [73.8600, 18.5250] },
      distanceField: "distanceMeters",
      maxDistance: 5000,
      spherical: true
    }
  },
  { $project: { _id: 0, name: 1, distanceMeters: 1 } }
])

Each result carries the place name and its distance in meters, which makes it easy to show "1.2 km away" labels in an application.

Choosing the Right Tool

QuestionTool
What is closest to me, sorted by distance?$near
What lies inside this circle or polygon?$geoWithin
Which area contains this point?$geoIntersects
How far is each result?$geoNear stage

Good Practices

  • Double-check the longitude and latitude order before loading data.
  • Create the 2dsphere index before running proximity queries.
  • Combine location filters with normal filters, such as { category: "cafe" }, to narrow results.
  • Round stored coordinates to a sensible number of decimals. Six decimals describe a position to within about ten centimeters.

Summary

Geospatial queries let MongoDB answer questions about places. GeoJSON points store locations with longitude first, and a 2dsphere index makes searches fast. The $near operator sorts by distance, $geoWithin searches inside shapes, $geoIntersects finds containing areas, and the $geoNear stage reports exact distances.

Leave a Comment

Your email address will not be published. Required fields are marked *