1Geospatial Indexing Example
2===========================
3
4.. testsetup::
5
6  from pymongo import MongoClient
7  client = MongoClient()
8  client.drop_database('geo_example')
9
10This example shows how to create and use a :data:`~pymongo.GEO2D`
11index in PyMongo. To create a spherical (earth-like) geospatial index use :data:`~pymongo.GEOSPHERE` instead.
12
13.. mongodoc:: geo
14
15Creating a Geospatial Index
16---------------------------
17
18Creating a geospatial index in pymongo is easy:
19
20.. doctest::
21
22  >>> from pymongo import MongoClient, GEO2D
23  >>> db = MongoClient().geo_example
24  >>> db.places.create_index([("loc", GEO2D)])
25  u'loc_2d'
26
27Inserting Places
28----------------
29
30Locations in MongoDB are represented using either embedded documents
31or lists where the first two elements are coordinates. Here, we'll
32insert a couple of example locations:
33
34.. doctest::
35
36  >>> result = db.places.insert_many([{"loc": [2, 5]},
37  ...                                 {"loc": [30, 5]},
38  ...                                 {"loc": [1, 2]},
39  ...                                 {"loc": [4, 4]}])  # doctest: +ELLIPSIS
40  >>> result.inserted_ids
41  [ObjectId('...'), ObjectId('...'), ObjectId('...'), ObjectId('...')]
42
43.. note:: If specifying latitude and longitude coordinates in :data:`~pymongo.GEOSPHERE`, list the **longitude** first and then **latitude**.
44
45Querying
46--------
47
48Using the geospatial index we can find documents near another point:
49
50.. doctest::
51
52  >>> import pprint
53  >>> for doc in db.places.find({"loc": {"$near": [3, 6]}}).limit(3):
54  ...   pprint.pprint(doc)
55  ...
56  {u'_id': ObjectId('...'), u'loc': [2, 5]}
57  {u'_id': ObjectId('...'), u'loc': [4, 4]}
58  {u'_id': ObjectId('...'), u'loc': [1, 2]}
59
60.. note:: If using :data:`pymongo.GEOSPHERE`, using $nearSphere is recommended.
61
62The $maxDistance operator requires the use of :class:`~bson.son.SON`:
63
64.. doctest::
65
66  >>> from bson.son import SON
67  >>> query = {"loc": SON([("$near", [3, 6]), ("$maxDistance", 100)])}
68  >>> for doc in db.places.find(query).limit(3):
69  ...   pprint.pprint(doc)
70  ...
71  {u'_id': ObjectId('...'), u'loc': [2, 5]}
72  {u'_id': ObjectId('...'), u'loc': [4, 4]}
73  {u'_id': ObjectId('...'), u'loc': [1, 2]}
74
75It's also possible to query for all items within a given rectangle
76(specified by lower-left and upper-right coordinates):
77
78.. doctest::
79
80  >>> query = {"loc": {"$within": {"$box": [[2, 2], [5, 6]]}}}
81  >>> for doc in db.places.find(query).sort('_id'):
82  ...     pprint.pprint(doc)
83  {u'_id': ObjectId('...'), u'loc': [2, 5]}
84  {u'_id': ObjectId('...'), u'loc': [4, 4]}
85
86Or circle (specified by center point and radius):
87
88.. doctest::
89
90  >>> query = {"loc": {"$within": {"$center": [[0, 0], 6]}}}
91  >>> for doc in db.places.find(query).sort('_id'):
92  ...   pprint.pprint(doc)
93  ...
94  {u'_id': ObjectId('...'), u'loc': [2, 5]}
95  {u'_id': ObjectId('...'), u'loc': [1, 2]}
96  {u'_id': ObjectId('...'), u'loc': [4, 4]}
97
98geoNear queries are also supported using :class:`~bson.son.SON`::
99
100  >>> from bson.son import SON
101  >>> db.command(SON([('geoNear', 'places'), ('near', [1, 2])]))
102  {u'ok': 1.0, u'stats': ...}
103
104.. warning:: Starting in MongoDB version 4.0, MongoDB deprecates the **geoNear** command. Use one of the following operations instead.
105
106  * $geoNear - aggregation stage.
107  * $near - query operator.
108  * $nearSphere - query operator.
109