Sling Academy
Home/MongoDB/Using the $geoNear Stage in MongoDB

Using the $geoNear Stage in MongoDB

Last updated: February 01, 2024

Introduction

Geospatial queries are an essential feature for contemporary applications like location-based services, real estate apps, or any platform requiring location intelligence. MongoDB offers powerful geospatial capabilities, among which the $geoNear stage in the aggregation framework is a vital tool for performing proximity searches. In this tutorial, we delve into the nuts and bolts of using the $geoNear stage to execute geospatial queries and harness the full potential of MongoDB’s geospatial querying power.

Getting Started with Geospatial Data

Before we can use $geoNear, we need to ensure our data is geospatially indexed. MongoDB supports two types of geospatial data: 2dsphere and 2d. The 2dsphere index is used for Earth-like spheres and supports GeoJSON objects with coordinates in longitude and latitude. The 2d index is intended for flat surfaces and legacy coordinate pairs.

To create a 2dsphere index:

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

With the index in place, you can now store documents with geospatial data:

db.places.insert({
  name: "Central Park",
  location: { type: "Point", coordinates: [-73.97, 40.77] }
})

Ensure your coordinate pairs follow longitude, latitude order when dealing with 2dsphere indexes.

Understanding the $geoNear Stage

The $geoNear stage outputs documents in order of nearest to farthest from a specified point. It only works as the first stage in an aggregation pipeline.

A basic $geoNear example:

db.places.aggregate([
  {
    $geoNear: {
      near: { type: "Point", coordinates: [-73.98, 40.76] },
      distanceField: "dist.calculated",
      maxDistance: 2000,
      query: { type: "public" },
      includeLocs: "dist.location",
      spherical: true
    }
  }
])

Let’s break down the essential parameters:

  • near: Defines the reference point for distance calculations.
  • distanceField: A required field that specifies the name of the field to store the calculated distance.
  • maxDistance: Limits results to those within a specified distance in meters.
  • query: Filters the results by additional query expressions.
  • includeLocs: Optionally includes the location of the matching documents.
  • spherical: Calculates distances using spherical geometry.

Advanced Usage of $geoNear

The $geoNear stage is versatile. For example, you can limit the number of results and project additional fields:

db.places.aggregate([
  {
    $geoNear: {
      ...
      num: 5,
      spherical: true
    }
  },
  {
    $project: {
      name: 1,
      formattedDistance: {
        $concat: [
          { $toString: "$dist.calculated" }, " m"
        ]
      }
    }
  }
])

If you want to work with specific Earth radius measurements or convert results to miles or kilometers:

db.places.aggregate([
  {
    $geoNear: {
      ...
      distanceMultiplier: 0.001,
      spherical: true
    }
  }
])

Here, distanceMultiplier converts our distance from meters to kilometers.

Handling Large Datasets

Efficiency with large geospatial datasets can be improved by compound indexes that combine a geospatial index with other queryable fields:

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

You can then execute more focused queries that benefit from index filtering.

Geospatial Aggregation with $geoNear

Beyond simple proximity searches, one can perform powerful aggregations that combine the $geoNear stage with others:

db.places.aggregate([
  {
    $geoNear: { ...
      }
  },
  {
    $group: {
      _id: "$type",
      averageDistance: { $avg: "$dist.calculated" }
    }
  }
])

This might, for instance, calculate the average distance of points of interest from a location.

Common Pitfalls and Best Practices

Using $geoNear, be aware of potential pitfalls. Misunderstanding spherical geometry or coordinate systems can lead to inaccurate results. Additionally, consider proper indexing and query optimization to avoid performance hits for large datasets.

Best practices include using latest versions of MongoDB, thoroughly testing your geo-queries, and monitoring performance in production setups.

Conclusion

Mastering $geoNear unlocks a new dimension of query capability in MongoDB. Through examples and explanations, we’ve shown how to harness this potential to execute complex geospatial queries. Whether building a location-based application or mining geo-datasets for insights, MongoDB’s $geoNear provides a robust foundation to build upon.

Next Article: Geospatial Indexes in MongoDB: How to Speed Up Geospatial Queries

Previous Article: Working with the $unwind stage in MongoDB

Series: MongoDB Tutorials

MongoDB

You May Also Like

  • MongoDB: How to combine data from 2 collections into one
  • Hashed Indexes in MongoDB: A Practical Guide
  • Partitioning and Sharding in MongoDB: A Practical Guide (with Examples)
  • Geospatial Indexes in MongoDB: How to Speed Up Geospatial Queries
  • Understanding Partial Indexes in MongoDB
  • Exploring Sparse Indexes in MongoDB (with Examples)
  • Using Wildcard Indexes in MongoDB: An In-Depth Guide
  • Matching binary values in MongoDB: A practical guide (with examples)
  • Understanding $slice operator in MongoDB (with examples)
  • Caching in MongoDB: A practical guide (with examples)
  • CannotReuseObject Error: Attempted illegal reuse of a Mongo object in the same process space
  • How to perform cascade deletion in MongoDB (with examples)
  • MongoDB: Using $not and $nor operators to negate a query
  • MongoDB: Find SUM/MIN/MAX/AVG of each group in a collection
  • References (Manual Linking) in MongoDB: A Developer’s Guide (with Examples)
  • MongoDB: How to see all fields in a collection (with examples)
  • Type checking in MongoDB: A practical guide (with examples)
  • How to query an array of subdocuments in MongoDB (with examples)
  • MongoDB: How to compare 2 documents (with examples)