具有以下映射:
function (doc, meta) {
emit(dateToArray(doc.timestamp), doc.user_id);
}
我需要在这个reduce上做什么更改来获得不止一次发生的user_ids
计数?
function(key, values, rereduce) {
var counts = {}, id;
for (var i = 0; i < values.length; i++) {
id = values[i].replace('-', '_');
counts[id] = counts[id] || 0;
counts[id] = counts[id] + 1;
}
var total = 0;
for (id in counts) {
if (counts[id] > 1) total++;
}
return total;
}
我在纯JS上尝试过传递一些值数组,它的工作原理如我所料。在Couchbase上调试是困难的(或者我不知道为什么),我没有看到error.1
和mapreduce_errors.1
文件上的任何错误。
更新:我一直在做一些粗略的调试,逐行,这是我目前为止的成果:
function(key, values, rereduce) {
var counts = {}, total = 0;
for (var i = 0; i < values.length; i++) {
var id = values[i];
if (id.indexOf('id_') != 0) id = 'id_' + values[i].replace(/-/g, '_');
return id;
counts[id] = counts[id] || 0;
counts[id] = counts[id] + 1;
}
for (id in counts) {
if (counts[id] > 1) total++;
}
return total;
}
注意return id;
行。它返回一个修改后的uuid,前缀为"id_",正如您在查看代码时所期望的那样。
但是,如果我将该行更改为return counts;
或return total;
,则Couchbase的结果是"此视图的结果为空"。到底发生了什么事?
这是一个痛苦的调试过程,但这是最终的解决方案:
function(key, values, rereduce) {
var counts = {}, total = 0, id;
if (rereduce) {
for (var set in values) {
for (var i in values[set]) {
counts[i] = (counts[i] || 0) + values[set][i];
}
}
for (f in counts) {
if (counts[f] > 1) total++;
}
return total;
} else {
for (var i in values) {
id = 'id_' + values[i].replace(/-/g, '_');
counts[id] = (counts[id] || 0) + 1;
}
return counts;
}
}
一个额外的教训:Couchbase不会从reduce操作返回大对象。我得多学学这个