In my database I have (not only) two types of documents in a one-to-many relationship. I tried to manage this like the following example shows:
{
_id : "class:xyz"
type: "class"
... other keys ...
}
{
_id : "class:xyz:pupil:abc"
type: "pupil"
... other keys ...
}
If I query my docs with allDocs()
like
http://url_of_my_server:5984/my_database/_all_docs?include_docs=true&?startkey="class:xyz:pupil:"&endkey="class:xyz:pupil:\ufff0"
I get all docs of type pupil
related to the mentioned doc of type class
like wanted.
For performance I had the idea to introduce a design document to query only the docs of type pupil
and not all docs every time:
{
"_id": "_design/types",
"language": "javascript",
"views": {
"classes": {
"map": "function(doc){ if(doc.type == \"class\"){emit(doc.id, doc);} }"
},
"pupils": {
"map": "function(doc){ if(doc.type == \"pupil\"){emit(doc.id, doc);} }"
},
}
}
But if I query with this design document like
http://url_of_my_server:5984/my_database/_design/types/_view/pupils?include_docs=true&?startkey="class:xyz:pupil:"&endkey="class:xyz:pupil:\ufff0"
I get no result (only an empty array/no rows).
Where is my mistake or what is wrong in my conception? I actually have no idea? Thanks in advance for your advice.
First, for a view never emit
the document as a value; it is quite redundant since one may use include_docs=true
- and worse, it consumes storage unnecessarily.
Assuming two documents
{
_id : "class:xyz:pupil:abc"
type: "pupil"
},
{
_id : "class:xyz:pupil:xyz"
type: "pupil"
}
And the map function for pupils
"pupils": {
"map": "function(doc){ if(doc.type == \"pupil\"){emit(doc.id, doc);} }"
}
The view index for pupils
looks like this
id | key | value |
---|---|---|
class:xyz:pupil:abc | null | {"_id": "class:xyz:pupil:abc", /* etc */ } |
class:xyz:pupil:xyz | null | {"_id": "class:xyz:pupil:xyz", /* etc */ } |
So the key
columns are null because the map function is emitting doc.id
as the key.
See it? doc.id
is undefined - emit(doc._id)
instead.
Fix the design document map functions (including not emitting doc as value)
{
"_id": "_design/types",
"views": {
"classes": {
"map": "function(doc){ if(doc.type == \"class\"){emit(doc._id);} }"
},
"pupils": {
"map": "function(doc){ if(doc.type == \"pupil\"){emit(doc._id);} }"
}
}
}
Given the two hypothetical documents, the pupils
index now looks like this
id | key | value |
---|---|---|
class:xyz:pupil:abc | class:xyz:pupil:abc | null |
class:xyz:pupil:xyz | class:xyz:pupil:abc | null |
Now that the view index's key
has a value the query will operate as intended.
I highly recommend using Fauxton as it provides a quick means to view an index among other things.