1
votes

I have some documents with a "status" field of "Green", "Red", "Amber".

I'm sure it's possible to use MapReduce to produce a grouped response containing three keys (one for each status), each with a value containing an array of all the documents with that key. However, I'm struggling on how to use re(reduce) functions.

Map function:

function(doc) {
  emit(doc.status, doc);
}

Reduce function: ???

2

2 Answers

5
votes

This is not a problem that reduce is intended to solve; reduce in CouchDB is for aggregation.

If I understand you correctly, you want this;

Map:

function(doc) {
  for (var i in doc.status) {
    emit(doc.status[i], null);
  }
}

You can then find all docs of status Green with;

/_design/foo/_view/bar?key="Green"&include_docs=true

This will return a list of all docs with that status. If you wish to find docs of more than one status in a single query, then use http POST with a body of this form;

{"keys":["Green", "Red"]}

HTH, B.

2
votes

Generally speaking, you will not use a reduce function to obtain your list of documents. A reduce is meant to take a list, and reduce it to a single value. In fact, there is an upper limit to the size of a reduce value anyways, and using entire documents will trigger a reduce_overflow error. Examples of reduces are counts, sums, averages, etc. Stick with the map query, and you will have your values collated and sorted by the status value.

On another, possibly unrelated note, I would not emit the document with your view. You can just use the include_docs view query parameter, and achieve the same effect, while saving disk-space in the process. The trade-off is that internally the doc will have to be retrieved one-by-one. (but since they're indexed already by _id anyways, it's usually a negligible difference.