user3677331
user3677331

Reputation: 698

Cloudant couchdb changes api and geospatial indexes

Currently I'm doing filtered replication by monitoring the below resource:

_changes?filter=_selector&include_docs=true&attachments=true&limit=20

As you can see, I'm using a selector defined by

"selector": {
  "type": "Property"
}

and everything is working great. Now I need to add another criteria which is geospatial index. I want to replicate documents with locations in a radius. e.g. lat=-11.05987446&lon=12.28339928&radius=100 How can I replicate using the above filtered replication technique and replicate documents within a radius? Thanks

Upvotes: 0

Views: 206

Answers (2)

Will Holley
Will Holley

Reputation: 1765

The selector filter for _changes is not backed by an index - it just uses the same syntax as Query selectors, which currently does not support geospatial operations.

I think you have 3 options:

1. Use a bounding box

Your selector would then look something like:

"selector": {
  "type": "Property",
  "lat": {
    "$gt": -11
  },
  "lat": {
    "$lt": 11
  },
  "lon": {
    "$gt": 12
  },
  "lon": {
    "$lt": 14
  }
}

Perhaps you could then further restrict the results on the client if you need exactly a radial search.

2. Implement a radius search in a JavaScript filter

This means dropping the use of the `selector, would be relatively slow (anything that involves JavaScript in Couch/Cloudant will be) but gives you exactly the result you want.

3. Run a query and replicate the resulting ids

Use a search or geospatial query to get the set of _ids you need and use a doc_id based replication to fetch them.

Lastly, it's worth considering whether you really want replication (which implies the ability for documents to sync both ways) or if you're just caching / copying data to the client. Replication carries some overhead beyond just copying the data (it needs to figure out the delta between the client and server, retrieve the rev history for each doc, etc) so, if you don't need to write the docs back to the server, maybe you don't need it.

If you do go down the replication route, you may need to handle cases where documents that you previously replicated no longer match the query so updates do not propagate in subsequent replications.

If not, you may be better off just running a query with include_docs=true and manually inserting the documents to a local database.

Upvotes: 3

xpqz
xpqz

Reputation: 3737

The _selector filter for the changes feed isn't backed by an index, it's basically a handy shortcut to achieve the same thing as a javascript filter, but much faster as it's executed directly in the Erlang.

As it's not index-backed, you can't tap into a geo-index that way.

You'd be better off to run either a bounding box or radius query to get the ids and then fetch those documents with a bulk_get or with a post to all_docs with the ids in the body.

https://cloudant.com/wp-content/uploads/Cloudant-Geospatial-technical-overview.pdf

Upvotes: 1

Related Questions