Kotori
Kotori

Reputation: 1

Couchbase View - how to search multiple keys contained in different arrays within a document

I need to create a map function for couchbase view, that receives several keys and some of them are stored deeper in the document structure. I can't use N1QL, because I have to use couchbase version 3.0 and the search of a query with two "UNNEST" takes too much time (array indexing can be done from version 3.5 if I understand correctly).

I know how to search one key in an array from example explained on couchbase web: http://docs.couchbase.com/admin/admin/Views/views-querySample.html

But how do I search more than one key in more than one array? Is that even possible?

Lets say, I have this document structure:

{
    "title": "Fried chilli potatoes",
    "servings": "4",
    "totaltime": "30",
    "ingredients": [
        {
            "ingredient": "chilli powder",
            "meastext": "3-6 tsp"
        },
        {
            "ingredient": "potatoes",
            "meastext": "900 g"
        },
        {
            "ingredient": "vegetable oil",
            "meastext": ""
        }
       ...
    ],
    "actions": [
        {
            "action": "frying",
            "subject": "chicken wings",
            "time": "10 min"
        },
        {
            "action": "boiling",
            "subject": "potatoes",
            "time": "15 min"
        },
       ...
    ]
}

If I wanted to search all the recepies that require potatoes, the map function would be:

function(doc, meta)
{
  if (doc.ingredients)
  {
    for (i=0; i < doc.ingredients.length; i++)
    {
        emit(doc.ingredients[i].ingredient, null);
    }
  }
}

How do I find documents that have "potatoes" in the list of ingredients and have "frying" in the list of actions plus some more information, that are on the first level of document (like servings and totaltime)?

So I guess the keys returned in emit function should look like:

emit([doc.ingredients[i].ingredient, doc.actions[i].action, doc.servings, doc.totaltime], null)

Query: ->key(["potato", "frying", "4", "30"])

But I don't know how to write the cycles.

Upvotes: 0

Views: 86

Answers (1)

avsej
avsej

Reputation: 3972

The only option is to emit all possible permutations of the key

emit([doc.ingredients[i].ingredient, doc.actions[i].action, doc.servings, doc.totaltime], null)
emit([doc.ingredients[i].ingredient, doc.actions[i].action, doc.totaltime, doc.servings], null)
emit([doc.ingredients[i].ingredient, doc.servings, doc.actions[i].action, doc.totaltime], null)
emit([doc.ingredients[i].ingredient, doc.servings, doc.totaltime, doc.actions[i].action], null)
emit([doc.ingredients[i].ingredient, doc.totaltime, doc.actions[i].action, doc.servings], null)
emit([doc.ingredients[i].ingredient, doc.totaltime, doc.servings, doc.actions[i].action], null)
emit([doc.actions[i].action, doc.ingredients[i].ingredient, doc.totaltime, doc.servings], null)
emit([doc.actions[i].action, doc.ingredients[i].ingredient, doc.servings, doc.totaltime], null)
emit([doc.actions[i].action, doc.servings, doc.totaltime, doc.ingredients[i].ingredient], null)
emit([doc.actions[i].action, doc.servings, doc.ingredients[i].ingredient, doc.totaltime], null)
emit([doc.actions[i].action, doc.totaltime, doc.servings, doc.ingredients[i].ingredient], null)
emit([doc.actions[i].action, doc.totaltime, doc.ingredients[i].ingredient, doc.servings], null)
emit([doc.servings, doc.ingredients[i].ingredient, doc.actions[i].action, doc.totaltime], null)
emit([doc.servings, doc.ingredients[i].ingredient, doc.totaltime, doc.actions[i].action], null)
emit([doc.servings, doc.actions[i].action, doc.ingredients[i].ingredient, doc.totaltime], null)
emit([doc.servings, doc.actions[i].action, doc.totaltime, doc.ingredients[i].ingredient], null)
emit([doc.servings, doc.totaltime, doc.ingredients[i].ingredient, doc.actions[i].action], null)
emit([doc.servings, doc.totaltime, doc.actions[i].action, doc.ingredients[i].ingredient], null)
emit([doc.totaltime, doc.ingredients[i].ingredient, doc.servings, doc.actions[i].action], null)
emit([doc.totaltime, doc.ingredients[i].ingredient, doc.actions[i].action, doc.servings], null)
emit([doc.totaltime, doc.actions[i].action, doc.servings, doc.ingredients[i].ingredient], null)
emit([doc.totaltime, doc.actions[i].action, doc.ingredients[i].ingredient, doc.servings], null)
emit([doc.totaltime, doc.servings, doc.actions[i].action, doc.ingredients[i].ingredient], null)
emit([doc.totaltime, doc.servings, doc.ingredients[i].ingredient, doc.actions[i].action], null)

Upvotes: 2

Related Questions