How to get filtered changes in python couchdb

1.1k views Asked by At

I'm using python-couchdb library to listen to the changes in database using continuous feed. I want to apply a filter which gives me only those documents that have a key read equal to true.

With normal HTTP GET request, I get the desired results. But I'm not able to figure out how to do this via couchdb-python library. Here is a custom filter that I've written:

def read_true_filter():
    return """function(doc, req) {
            if(doc.read === true) {
                return true;
            }
            return false;
        }
        """

Here is how I'm trying to listen to the changes:

db_changes = db.changes(
    feed='continuous',
    include_docs=True,
    heartbeat=1000,
    since=last_seq_id,
    filter=read_true_filter
)

But this gives me the error:

Traceback (most recent call last):
  File "../src/couch_pull_pipeline.py", line 87, in <module>
    db_changes = db.changes(
  File "/Users/sanyam/venv/lib/python3.5/site-packages/couchdb/client.py", line 1027, in _changes
    _, _, data = self.resource.get('_changes', **opts)
  File "/Users/sanyam/venv/lib/python3.5/site-packages/couchdb/http.py", line 546, in get
    return self._request('GET', path, headers=headers, **params)
  File "/Users/sanyam/venv/lib/python3.5/site-packages/couchdb/http.py", line 581, in _request
    credentials=self.credentials)
  File "/Users/sanyam/venv/lib/python3.5/site-packages/couchdb/http.py", line 421, in request
    raise ServerError((status, error))
couchdb.http.ServerError: (400, ('bad_request', 'filter parameter must be of the form `designname/filtername`'))

Adding designname in the request is simple, but I couldn't find equivalent of doing this using couchdb client.

Is it possible using the python library or I should use simple HTTP requests or a better idea is to have the filter on the couchdb server itself? (As per what I've read so far, it is not a good idea to have that filter in couchdb due to performance reasons.)

Can someone provide me pointer on what I'm doing wrong / how to go about it?

1

There are 1 answers

0
Sanyam Khurana On BEST ANSWER

I figured this out. I made a design document in the database where I wanted to filter the contents like:

{
   "_id": "_design/read_validator",
   "_rev": "1-bd5fb337899a0eaf485b2112b439cc30",
   "filters": {
       "read_only_true": "function(doc, req) {if(doc.read === true) {return true;}return false;}"
   }
}

Here read_validator is the design document which includes the filter to return docs which has read attribute set to true. In the couchdb python client, while getting continuous feed, I gave the filter resource path as a string design_document_name/filter_name where design_document is the name of design document created in the db (in this case it is read_validator) and filter_name is the name of the filter (in this case it is read_only_true). So, the connection is like this:

db_changes = db.changes(
    feed='continuous',
    include_docs=True,
    heartbeat=1000,
    since=last_seq_id,
    filter="read_validator/read_only_true"
)

Here db_changes would be a continuous feed generator through which all the documents could be fetched through iterating, that have read key equal to true.