Meaning of the map function in couchdb-pythons ViewField
-
28-10-2019 - |
Question
I'm using the couchdb.mapping in one of my projects. I have a class called SupportCase
derived from Document
that contains all the fields I want.
My database (called admin
) contains multiple document types. I have a type
field in all the documents which I use to distinguish between them. I have many documents of type "case"
which I want to get at using a view. I have design document called support
with a view inside it called cases
. If I request the results of this view using db.view("support/cases)
, I get back a list of Row
s which have what I want.
However, I want to somehow have this wrapped by the SupportCase
class so that I can call a single function and get back a list of all the SupportCase
s in the system. I created a ViewField
property
@ViewField.define('cases')
def all(self, doc):
if doc.get("type","") == "case":
yield doc["_id"], doc
Now, if I call SupportCase.all(db)
, I get back all the cases.
What I don't understand is whether this view is precomputed and stored in the database or done on demand similar to db.query
. If it's the latter, it's going to be slow and I want to use a precomputed view. How do I do that?
Solution
I think what you need is:
@classmethod
def all(cls):
result = cls.view(db, "support/all", include_docs=True)
return result.rows
Document
class has a classmethod view
which wraps the rows by class on which it is called. So the following returns you a ViewResult
with rows of type SupportCase
and taking .rows
of that gives a list of support cases.
SupportCase.view(db, viewname, include_docs=True)
And I don't think you need to get into the ViewField magic. But let me explain how it works. Consider the following example from the CouchDB-python
documentation.
class Person(Document):
@ViewField.define('people')
def by_name(doc):
yield doc['name'], doc
I think this is equivalent to:
class Person(Document):
@classmethod
def by_name(cls, db, **kw):
return cls.view(db, **kw)
With the original function attached to People.by_name.map_fun
.
OTHER TIPS
The map function is in some ways analogous to an index in a relational database. It is not done again every time, and when new documents are added the way it is updated does not require everything to be redone (it's a kind of tree structure).
This has a pretty good summary
ViewField uses a pre-defined view so, once built, will be fast. It definitely doesn't use a temporary view.