couchbasecouchbase-view

couchbase Reduce gives not wanted result


I have a map function that returns a result like this :

{"total_rows":100995,"rows":[
{"id":"00001_372792","key":["00001","CADENCIER",0],"value":-0.1961035657664066},
{"id":"00001_372792","key":["00001","CADENCIER",0],"value":-0.1961035657664066},
{"id":"00001_386302","key":["00001","CADENCIER",0],"value":0.6934708647727543},
{"id":"00001_386302","key":["00001","CADENCIER",0],"value":0.6934708647727543},
{"id":"00001_386963","key":["00001","CADENCIER",0],"value":0.6922628824612621},
{"id":"00001_386963","key":["00001","CADENCIER",0],"value":0.6922628824612621},
{"id":"00001_387089","key":["00001","CADENCIER",0],"value":0.6919048724571887},
{"id":"00001_387089","key":["00001","CADENCIER",0],"value":0.6919048724571887},
{"id":"00001_387091","key":["00001","CADENCIER",0],"value":0.6919048724571887},
{"id":"00001_387091","key":["00001","CADENCIER",0],"value":0.6919048724571887},
{"id":"00001_387099","key":["00001","CADENCIER",0],"value":0.6921140124188077},
{"id":"00001_387099","key":["00001","CADENCIER",0],"value":0.6921140124188077},
{"id":"00001_387105","key":["00001","CADENCIER",0],"value":0.6921140124188077},
{"id":"00001_387105","key":["00001","CADENCIER",0],"value":0.6921140124188077},
{"id":"00001_387193","key":["00001","CADENCIER",0],"value":0.6936603115840247},
{"id":"00001_387193","key":["00001","CADENCIER",0],"value":0.6936603115840247},
{"id":"00001_387848","key":["00001","CADENCIER",1],"value":-0.29332158594360835},
{"id":"00001_387848","key":["00001","CADENCIER",1],"value":-0.29332158594360835},
{"id":"00001_388313","key":["00001","CADENCIER",1],"value":-0.0461553701861542},
{"id":"00001_388313","key":["00001","CADENCIER",1],"value":-0.0461553701861542},
{"id":"00001_388806","key":["00001","CADENCIER",1],"value":-0.04833054041013961},
{"id":"00001_388806","key":["00001","CADENCIER",1],"value":-0.04833054041013961},
{"id":"00001_388897","key":["00001","CADENCIER",1],"value":-0.25761199232338083},
{"id":"00001_388897","key":["00001","CADENCIER",1],"value":-0.25761199232338083},
{"id":"00001_435016","key":["00001","CADENCIER",1],"value":-0.037149057843773745},
{"id":"00001_435016","key":["00001","CADENCIER",1],"value":-0.037149057843773745}
...
]}

I want to reduce to group by key and return the count of values of each key as well as some other calculation on the values.

I did this:

function (key, values, rereduce) {

  var result = {};
  var ecartsSum;
  for(var i = 0; i < values.length; i++) {
    ecartsSum =+ values[i];
  }
  result.productsNumber = values.length;
  result.index = 100 + (Math.tan(ecartsSum/values.length)) * 100
  return result;
}

When I request the view using the key ["00001","CADENCIER",0]

I get this result :

{
  "productsNumber": 3,
  "index": null
}

which is not at all the result I was expecting.

PS: I use these options to select : connection_timeout=600000000&full_set=true&group=true&inclusive_end=true&key=%5B%2200001%22,%22CADENCIER%22,0%5D&limit=6&reduce=true&skip=0&stale=false


Solution

  • Not all values for a given key are passed to the reduce function at one time. The MapReduce view will work on subsets of the data, reducing each subset and combining them using the same reduce function until all values have been processed.

    You'll need to use the rereduce argument so the function can reduce the output from previous calls to itself.

    From the Re-reduce Argument documentation:

    In order to handle incremental map/reduce functionality (i.e. updating an existing view), each function must also be able to handle and consume the functions own output. This is because in an incremental situation, the function must be handle both the new records, and previously computed reductions.

    Try something like this example from the documentation:

    function(key, values, rereduce) {
      var result = {total: 0, count: 0};
      for(i=0; i < values.length; i++) {
        if(rereduce) {
            result.total = result.total + values[i].total;
            result.count = result.count + values[i].count;
        } else {
            result.total = sum(values);
            result.count = values.length;
        }
      }
      return(result);
    }