问题出在您的自定义 reduce 函数中:当它作为 re-reduce 的一部分被调用时,您没有处理这种情况。
根据Couchbase 文档:
reduce() 函数的基本格式如下:
function(key, values, rereduce) {
...
return retval;
}
reduce 函数提供了三个参数:
key
: key 是从 map() 函数和 group_level 参数派生的唯一键。
values
: values 参数是与特定键匹配的所有值的数组。例如,如果相同的键被输出 3 次,则 data 将是一个包含三个项目的数组,其中每个项目都包含 emit() 函数输出的值。
rereduce
:rereduce 指示函数是否作为re-reduce 的一部分被调用,即再次调用reduce 函数以进一步减少输入数据。
何时rereduce
为假:
何时rereduce
为真:
粗体格式是我的,突出显示的单词非常重要:您应该考虑有时,您会收到keys
值为null
.
根据文档,您应该在函数内处理这种情况rereduce
,true
并且reduce()
您应该知道在这种情况下,keys
将是null
. 对于您的reduce()
函数,您可以执行以下操作:
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;
});
}
在这里,我首先处理重新减少阶段。为此,我将在values
参数中接收到的数组数组展平,然后删除合并后可能出现的重复项。
然后是您的原始代码,它返回keys
没有重复的参数数组。
为了测试这个reduce()
函数是否真的有效,我使用了以下map()
函数:
function(doc, meta) {
switch(doc.type) {
case "brewery":
emit(meta.id, null);
emit(meta.id, null);
break;
}
}
这会故意生成重复项,然后由reduce()
函数将其删除。