The problem is your custom reduction function: you are not handling the case when it is called as part of a repeated reduction.
According to Couchbase Documentation :
The basic format of the reduce () function is as follows:
function(key, values, rereduce) { ... return retval; }
The reduction function has three arguments:
key : a key is a unique key obtained from the map () function and the group_level parameter.
values : The argument of values ββis an array of all values ββthat match a particular key. For example, if the same key is displayed three times, the data will be an array of three elements containing, with each element containing the value output by the emit () function.
rereduce : Rereduce indicates whether the function is called as part of the reduction, that is, the called reduction function again to further reduce the input.
If rereduce false:
The argument argument key will be an array, where the first argument is the key emitted by the map function, and id is the document identifier generated by the key.
Values ββare an array of values, where each element of the array corresponds to the corresponding element in the keys array.
If rereduce true:
Bold formatting belongs to me, and the highlighted words are very important: you should think that sometimes you get the keys argument with a null value.
According to the docs, you should handle the case where rereduce is true in your reduce() function, and you should know that in this case the keys will be null . In the case of your reduce() function, you can do something like this:
function(keys, values, rereduce) { if (rereduce) { var result = []; for (var i = 0; i < values.length; i++) { var distinct = values[i]; for (var j = 0; j < distinct.length; j++) { result.push(distinct[j]); } } return result.filter(function (e, i, arr) { return arr.lastIndexOf(e) === i; }); } return keys.filter(function (e, i, arr) { return arr.lastIndexOf(e) === i; }); }
Here I first process the phase of re-reduction. To do this, I smooth out the array of arrays that I get in the values argument, and then remove the duplicates that might appear after the merge.
Then comes the source code, which returns an array of keys arguments without duplicates.
To verify that this reduce() function really works, I used the following map() function:
function(doc, meta) { switch(doc.type) { case "brewery": emit(meta.id, null); emit(meta.id, null); break; } }
This intentionally creates duplicates, which are then removed by the reduce() function.