Question

I want to be able to search emitted docs from a view, on fields that weren't part of it's generation but rather fields that are added by way of linked documents.

As explained in the docs

If these were my records: [ { "_id": "11111" , "name": "pandora" }, { "_id": "22222", "ancestors": ["11111"], "value": "hello" }, { "_id": "33333", "ancestors": ["22222","11111"], "value": "world" } ]

and the view was this:

    function(doc) {
    if (doc.value) {
    emit([doc.value, 0], null);
    if (doc.ancestors) {
      for (var i in doc.ancestors) {
        emit([doc.value, Number(i)+1], {_id: doc.ancestors[i]});
      }
    }     

Would it be possible to search the returned docs by sorting on 'name' ??

Was it helpful?

Solution

Unfortunately you can not search linked documents. They are linked to the couchdb document that was emitted. include_docs parameter just fetches the document corresponding to the _id for you. The view is sorted on the key and can only be filtered by the emitted key.

When a couchdb view is built sorting is done on the key that is emitted from the view. In your case the documents will be sorted on value and you can filter the results only by using key=some-value. However you can emit a complex json key like {value:doc.value,name:doc.name} and query on both name and value.

Unrelated to your question but cloudant has a couch-db lucene that can be used to cover all sorts of complex querying scenarios.

OTHER TIPS

I'd do what you suggest in a two view approach.

View 1 - Lookup the name to get the document _id

All you need to do here is to emit documents with a name. In the emit function you would emit the name as the key and the doc._id as the value. The output would look like this:

   key: "pandora", value: [11111]

You may need to reduce this if you have more than one id with the same name.

View 2 - Create the output you require per document _id

The second view is more complex. You could emit for each document with a value and store the 'position' by using an array with empty values. this could look like this:

    id 22222: key: 11111, value: ["hello"]
    id 33333: key: 22222, value: ["world"] 
    id 33333: key: 11111, value: ["","world"]

Assuming that there will always be at most one defined/non-empty entry per key and array position, your reduce function could reduce this to:

    key: 11111, value: ["hello","world"]
    key: 22222, value: ["world"]

Performance Concerns

You mentioned that the names update once per 15 seconds. Your documents look small so around 6k updates per day does not appear an issue to me. However, you should consider the following:

  • A view index is updated whenever you request it, not when the documents are updated.
  • Your views should first and foremost check if they can dismiss the document. You can dismiss documents with "name" in view 2 and documents with "value" in view 1.
  • I am not sure how often you'll access the view but you can use the key parameter on both views so you immediately get the document you want.
  • You can consider using stale views (this means that the view will be reindexed after returning the last set of results) so some very few responses may be out of date the first time you query the view after an update.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top