为什么我每100个文件丢失一些值?

时间:2012-09-21 16:15:31

标签: mongodb mapreduce

我正在尝试了解map / reduce的行为。

这是地图功能:

function() {
  var klass = this.error_class;
  emit('klass', { model : klass, count : 1 });
}

还原功能:

function(key, values) {
  var results = { count : 0, klass: { foo: 'bar' } };
  values.forEach(function(value) {
    results.count += value.count;
    results.klass[value.model] = 0;
    printjson(results);
  });
  return results;
}

然后我运行它:

{
  "count" : 85,
  "klass" : {
    "foo" : "bar",
    "Twitter::Error::BadRequest" : 0
  }
}
{
  "count" : 86,
  "klass" : {
    "foo" : "bar",
    "Twitter::Error::BadRequest" : 0,
    "Stream:DirectMessage" : 0
  }
}

在这一点上,一切都很好,但是这里每100个文件都会产生读取锁:

{
  "count" : 100,
  "klass" : {
    "foo" : "bar",
    "Twitter::Error::BadRequest" : 0,
    "Stream:DirectMessage" : 0
  }
}
{ "count" : 100, "klass" : { "foo" : "bar", "undefined" : 0 } }

我保留了我的密钥foo,并且我的count属性不断增加。问题是其他一切都成了undefined

那么,为什么我的count属性仍然不错时,我的对象会丢失动态键?

1 个答案:

答案 0 :(得分:0)

要记住你的reduce函数的一点是传递给它的值要么是map函数的输出,要么是之前调用reduce的返回值。

这是关键 - 它意味着可以将数据的部分映射/减少到不同的机器(例如mongo集群的不同分片),然后再次使用以重新组装数据。这也意味着mongo不必首先映射每个值,将所有结果保存在内存中,然后将它们全部减少:它可以映射和减少块,在必要时重新减少。

换句话说,必须符合以下条件:

reduce(k,[A,B,C]) == reduce(k, [A,  reduce(k,[A,B]))

你的reduce函数的输出没有model属性,所以如果它在重新减少中使用,那么这些未定义的值将会出现。

您需要让reduce函数返回类似于map函数发出的格式,以便您可以无差别地处理这两者(通常是最简单的),或者以不同方式处理重新缩减的值。