7

I have multiple CouchDB documents representing a timestamp with a property userId and tag (a user can have n timestamps and assign each one a tag). I want to query CouchDB by a specific userId and get a sorted list of tags the user has used (sorted by occurrence).

How would the view look like?

If I want to get a list of all tags sorted by occurrence (no matter from which user) or if I assume that there are only documents with the same userId, I would make it like so:

Map:

function(doc) {
  if(doc.tag) emit(doc.tag, 1); 
}

Reduce:

function(keys, values) {
  return sum(values);
}

But how do I group the result so that I can filter the query by a specific userId?

black666
  • 2,997
  • 7
  • 25
  • 40

1 Answers1

10

Answering my own question.

Seems like CouchDB supports arrays as keys. With that in mind it's pretty simple:

Map:

function(doc) {
  if(doc.tag) emit([doc.userId, doc.tag], 1); 
}

Reduce:

function(keys, values) {
  return sum(values);
}

The result is then sorted by userId & tag.

black666
  • 2,997
  • 7
  • 25
  • 40
  • 3
    Just to add to that, you can use the `group_level` view parameter to achieve varying levels of granularity to your reduce calculations. This is probably best demonstrated if you use a date as an array for your key. `[year, month, day]`. In this case, `group_level=1` will get you the aggregate for the year, `group_level=2` will go by month and `group_level=3` will be by day. – Dominic Barnes Apr 01 '11 at 14:08
  • 3
    And one other thing, if you just use `_sum` as your reduce function, CouchDB will automatically use a pre-written Erlang function that will perform much faster than the JavaScript equivalent. (other examples all documented [here](http://wiki.apache.org/couchdb/Built-In_Reduce_Functions)) – Dominic Barnes Apr 01 '11 at 14:10
  • This doesn't sort by occurrence, though. – Alex B Jul 25 '12 at 02:22
  • How could we order the result against the `sum(values)` instead of the key? Something like `ORDER BY COUNT(*) DESC` in SQL. – Lion Dec 27 '19 at 22:20