How can I query by document attribute when the attribute is an array?

44 views Asked by At

In Couchbase Server 3.0, the documents in my bucket are of the form:

{ "id":"xyz", "categories":["news", "articles", "etc.etc.."]}

I want to write a view such that when I specify key="news", all the documents that include "news" in the "categories" array attribute will be returned.

I went as far as writing a map function that emits the same article as many times as we have elements in "categories" array.

function (doc, meta) {
  for(var i = 0; i < doc.categories.length ; i++)
  emit(doc.categories[i], doc);
}

But I'm stuck with the reduce.

2

There are 2 answers

0
sscarduzio On

Turns out the map function is sufficient, I just needed to query with key="cateogoryName" in the URL.

I was initially confused because if you don't wrap the key in quotes in the query you get a very mysterious error, see: https://issues.couchbase.com/browse/MB-7555

Not sure if a reduce function would be more efficient though..

0
Remigius Stalder On

If you just want to query the data, you don't need a reduce function, i.e. you can leave it empty. You only need the reduce to perform calculations on the result set.

See also:

http://docs.couchbase.com/developer/dev-guide-3.0/built-in-reduce.html

However, you might change the map to the following:

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

and possibly check for a type in the if statement. You can emit null as second parameter, as there is no reduce function. This can be queried in Java e.g. as follows (async):

bucket.async()
      .query(query)
      .flatMap(AsyncViewResult::rows)
      .flatMap(AsyncViewRow::document)
      ...