Weixiang Guan
Weixiang Guan

Reputation: 487

CouchDB reduce error?

I have a sample database in CouchDB with the information of a number of aircraft, and a view which shows the manufacturer as key and the model as the value.

The map function is

function(doc) {
    emit(doc["Manufacturer"], doc._id)
}

and the reduce function is

function(keys, values, rereduce){
    return values.length;
}

This is pretty simple. And I indeed get the correct result when I show the view using Futon, where I have 26 aircraft of Boeing:

"BOEING"    26

But if I use a REST client to query the view using

http://localhost:6060/aircrafts/_design/basic/_view/VendorProducts?key="BOEING"

I get

{"rows":[
    {"key":null,"value":2}
]}

I have tested different clients (including web browser, REST client extensions, and curl), all give me the value 2! While queries with other keys work correctly.

Is there something wrong with the MapReduce function or my query?

Upvotes: 2

Views: 417

Answers (2)

Akshat Jiwan Sharma
Akshat Jiwan Sharma

Reputation: 16000

The issue could be because of grouping

Using group=true (which is Futon's default), you get a separate reduce value for each unique key in the map - that is, all values which share the same key are grouped together and reduced to a single value.

Were you passing group=true as a query parameter when querying with curl etc? Since it is passed by default in futon you saw the results like

BOEING : 26

Where as without group=true only the reduced value was being returned.

So try this query

http://localhost:6060/aircrafts/_design/basic/_view/VendorProducts?key="BOEING"&group=true

Upvotes: 2

Hans
Hans

Reputation: 2910

You seem to be falling into the re-reduce-trap. Couchdb strictly speaking uses a map-reduce-rereduce process.

  • Map: reformats your data in the output format.
  • Reduce: aggregates the data of several (but not all entries with the same key) - which works correctly in your case.
  • Re-reduce: does the same as reduce, but on previously reduced data.

As you change the format of the value in the reduce stage, the re-reduce call will aggregate the number of already reduced values.

Solutions:

  1. You can just set the value in the map to 1 and reduce a sum of the values.
  2. You check for rereduce==true and in that case return a sum of the values - which will be the integer values returned by the initial reduce.

Upvotes: 1

Related Questions