Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit eb859cb

Browse files
authored
Merge pull request #192 from cloudant/188-support-geospatial-indexes
Cloudant Geo property in design_document.py
2 parents 6b42554 + 86de9e9 commit eb859cb

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- [NEW] Added support for Cloudant Search index management.
55
- [NEW] Added support for managing and querying list functions.
66
- [NEW] Added ``rewrites`` accessor property for URL rewriting.
7+
- [NEW] Added ``st_indexes`` accessor property for Cloudant Geospatial indexes.
78
- [NEW] Added support for DesignDocument ``_info`` and ``_search_info`` endpoints.
89
- [NEW] Added support for a custom ``requests.HTTPAdapter`` to be configured using an optional ``adapter`` arg e.g.
910
``Cloudant(USERNAME, PASSWORD, account=ACCOUNT_NAME, adapter=Replay429Adapter())``.

src/cloudant/design_document.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,46 @@ def __init__(self, database, document_id=None):
4848
for prop in self._nested_object_names:
4949
self.setdefault(prop, dict())
5050

51+
@property
52+
def st_indexes(self):
53+
"""
54+
Provides an accessor property to the Cloudant Geospatial
55+
(a.k.a. Cloudant Geo) indexes dictionary in the locally cached
56+
DesignDocument. Each Cloudant Geo index is a JSON object within the
57+
``st_indexes`` containing an index name and a javascript function.
58+
59+
Note: To make it easier to work with Cloudant Geo documents, it is best
60+
practice to create a separate design document specifically for
61+
Cloudant Geo indexes.
62+
63+
Geospatial index example:
64+
65+
.. code-block:: python
66+
67+
# Add the Cloudant Geo index to ``st_indexes`` and save the design document
68+
ddoc = DesignDocument(self.db, '_design/ddoc001')
69+
ddoc['st_indexes'] = {
70+
'geoidx': {
71+
'index': 'function(doc) { '
72+
'if (doc.geometry && doc.geometry.coordinates) { '
73+
'st_index(doc.geometry);}} '
74+
}
75+
}
76+
ddoc.save()
77+
78+
Once the Cloudant Geo index is saved to the remote database, you can
79+
query the index with a GET request. To issue a request against the
80+
``_geo`` endpoint, see the steps outlined in the `endpoint access
81+
documentation <getting_started.html#endpoint-access>`_.
82+
83+
For more details, see the `Cloudant Geospatial
84+
documentation <https://docs.cloudant.com/geo.html>`_.
85+
86+
:return: Dictionary containing Cloudant Geo names and index objects
87+
as key/value
88+
"""
89+
return self.get('st_indexes')
90+
5191
@property
5292
def lists(self):
5393
"""

tests/unit/design_document_tests.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,5 +1352,58 @@ def test_get_list_function(self):
13521352
'html += \'</ol></body></html>\'; return html; }); }'
13531353
)
13541354

1355+
@unittest.skipUnless(
1356+
os.environ.get('RUN_CLOUDANT_TESTS') is not None,
1357+
'Skipping Cloudant specific Cloudant Geo tests'
1358+
)
1359+
def test_geospatial_index(self):
1360+
"""
1361+
Test retrieval and query of Cloudant Geo indexes from the DesignDocument.
1362+
"""
1363+
ddoc = DesignDocument(self.db, '_design/ddoc001')
1364+
ddoc['st_indexes'] = {
1365+
'geoidx': {
1366+
'index': 'function(doc) { '
1367+
'if (doc.geometry && doc.geometry.coordinates) { '
1368+
'st_index(doc.geometry);}} '
1369+
}
1370+
}
1371+
ddoc.save()
1372+
ddoc_remote = DesignDocument(self.db, '_design/ddoc001')
1373+
self.assertNotEqual(ddoc_remote, ddoc)
1374+
ddoc_remote.fetch()
1375+
self.assertEqual(ddoc_remote, {
1376+
'_id': '_design/ddoc001',
1377+
'_rev': ddoc['_rev'],
1378+
'st_indexes': ddoc['st_indexes'],
1379+
'indexes': {},
1380+
'views': {},
1381+
'lists': {}
1382+
})
1383+
# Document with geospatial point
1384+
geodoc = Document(self.db, 'doc001')
1385+
geodoc['type'] = 'Feature'
1386+
geodoc['geometry'] = {
1387+
"type": "Point",
1388+
"coordinates": [
1389+
-71.1,
1390+
42.3
1391+
]
1392+
}
1393+
geodoc.save()
1394+
# Geospatial query for a well known point
1395+
geo_result = self.client.r_session.get('/'.join([ddoc_remote.document_url,
1396+
'_geo',
1397+
'geoidx?g=point(-71.1%2042.3)'])).json()
1398+
self.assertIsNotNone(geo_result['bookmark'])
1399+
geo_result.pop('bookmark')
1400+
self.assertEqual(geo_result,
1401+
{'rows': [
1402+
{'id': 'doc001',
1403+
'geometry':
1404+
{'type': 'Point',
1405+
'coordinates': [-71.1, 42.3]}}]
1406+
})
1407+
13551408
if __name__ == '__main__':
13561409
unittest.main()

0 commit comments

Comments
 (0)