Geospatial Indexing Example
This example shows how to create and use a GEO2D
index in PyMongo. To create a spherical (earth-like) geospatial index use GEOSPHERE
instead.
See also
The MongoDB documentation on
Creating a Geospatial Index
Creating a geospatial index in pymongo is easy:
- >>> from pymongo import MongoClient, GEO2D
- >>> db = MongoClient().geo_example
- >>> db.places.create_index([("loc", GEO2D)])
- u'loc_2d'
Inserting Places
Locations in MongoDB are represented using either embedded documentsor lists where the first two elements are coordinates. Here, we’llinsert a couple of example locations:
- >>> result = db.places.insert_many([{"loc": [2, 5]},
- ... {"loc": [30, 5]},
- ... {"loc": [1, 2]},
- ... {"loc": [4, 4]}])
- >>> result.inserted_ids
- [ObjectId('...'), ObjectId('...'), ObjectId('...'), ObjectId('...')]
Note
If specifying latitude and longitude coordinates in GEOSPHERE
, list the longitude first and then latitude.
Querying
Using the geospatial index we can find documents near another point:
- >>> import pprint
- >>> for doc in db.places.find({"loc": {"$near": [3, 6]}}).limit(3):
- ... pprint.pprint(doc)
- ...
- {u'_id': ObjectId('...'), u'loc': [2, 5]}
- {u'_id': ObjectId('...'), u'loc': [4, 4]}
- {u'_id': ObjectId('...'), u'loc': [1, 2]}
Note
If using pymongo.GEOSPHERE
, using $nearSphere is recommended.
The $maxDistance operator requires the use of SON
:
- >>> from bson.son import SON
- >>> query = {"loc": SON([("$near", [3, 6]), ("$maxDistance", 100)])}
- >>> for doc in db.places.find(query).limit(3):
- ... pprint.pprint(doc)
- ...
- {u'_id': ObjectId('...'), u'loc': [2, 5]}
- {u'_id': ObjectId('...'), u'loc': [4, 4]}
- {u'_id': ObjectId('...'), u'loc': [1, 2]}
It’s also possible to query for all items within a given rectangle(specified by lower-left and upper-right coordinates):
- >>> query = {"loc": {"$within": {"$box": [[2, 2], [5, 6]]}}}
- >>> for doc in db.places.find(query).sort('_id'):
- ... pprint.pprint(doc)
- {u'_id': ObjectId('...'), u'loc': [2, 5]}
- {u'_id': ObjectId('...'), u'loc': [4, 4]}
Or circle (specified by center point and radius):
- >>> query = {"loc": {"$within": {"$center": [[0, 0], 6]}}}
- >>> for doc in db.places.find(query).sort('_id'):
- ... pprint.pprint(doc)
- ...
- {u'_id': ObjectId('...'), u'loc': [2, 5]}
- {u'_id': ObjectId('...'), u'loc': [1, 2]}
- {u'_id': ObjectId('...'), u'loc': [4, 4]}
geoNear queries are also supported using SON
:
- >>> from bson.son import SON
- >>> db.command(SON([('geoNear', 'places'), ('near', [1, 2])]))
- {u'ok': 1.0, u'stats': ...}
Warning
Starting in MongoDB version 4.0, MongoDB deprecates the geoNear command. Use one of the following operations instead.
- $geoNear - aggregation stage.
- $near - query operator.
- $nearSphere - query operator.