How to fetch multiple documents from CouchDB, in particular with couchdb-python?
3 Answers
Easiest way is to pass a include_docs=True arg to Database.view. Each row of the results will include the doc. e.g.
>>> db = couchdb.Database('http://localhost:5984/test')
>>> rows = db.view('_all_docs', keys=['docid1', 'docid2', 'missing'], include_docs=True)
>>> docs = [row.doc for row in rows]
>>> docs
[<Document 'docid1'@'...' {}>, <Document 'docid2'@'...' {}>, None]
Note that a row's doc will be None if the document does not exist.
This works with any view - just provide a list of keys suitable to the view.
1 Comment
Matt Goodall
True, but docs don't make any sense after a reduce anyway. A reduce combines items from multiple documents (the map's emitted (key, value) pairs) into a single result. Therefore, a reduce row is made up of many documents and the idea of a a reduce row's doc is meaningless. Of course, you can skip a view's reduce by passing a reduce=False keyword arg and that can be combined with include_docs=True just fine. But that's not a reduce any more; only a map.
This is the right way:
import couchdb
server = couchdb.Server("http://localhost:5984")
db = server["dbname"]
results = db.view("_all_docs", keys=["key1", "key2"])
2 Comments
dnolen
This is true only if you don't what fine grained control over the results. My method allows you ask for keys from _all_docs that don't exist, and you'll get back a empty placeholder for the non-existant keys. If you attempt this with your method you'll get an exception when iterating over the results. Why would want to do something like this? Fast manual joins. You have x documents and you want to join in data from other documents.
Walt W
@dnolen: Actually, that's not true... there's an error in the
__repr__ code for a row result, that is true, but you can just do [ row for row in db.view('_all_docs', keys=["key1", "key2"]).rows if 'value' in row ] to get rows that exist.import couchdb
import simplejson as json
resource = couchdb.client.Resource(None, 'http://localhost:5984/dbname/_all_docs')
params = {"include_docs":True}
content = json.dumps({"keys":[idstring1, idstring2, ...]})
headers = {"Content-Type":"application/json"}
resource.post(headers=headers, content=content, **params)
resource.post(headers=headers, content=content, **params)[1]['rows']
1 Comment
Walt W
-1: This answer was posted at the same time the question was asked, and was accepted over a more API-conforming answer that was posted before this solution was marked as accepted.