自定义Couchbase减少仅计算一些值

时间:2014-06-09 22:35:52

标签: mapreduce couchbase

拥有以下地图:

function (doc, meta) {
  emit(dateToArray(doc.timestamp), doc.user_id);
}

我需要对此进行哪些更改才能获得多次出现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.1mapreduce_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,前缀为&#34; id _&#34;,就像您期望查看代码一样。

但是,如果我将该行更改为return counts;return total;,则Couchbase的结果为&#34;此视图的结果为空。&#34;是什么给了什么?

1 个答案:

答案 0 :(得分:1)

这是一个痛苦的调试会议,但这是最终的解决方案:

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操作返回大对象。要了解更多相关信息。