【发布时间】:2013-05-16 06:50:39
【问题描述】:
我在 MongoDB 上有一个非常简单的 Map/Reduce 函数,它旨在从集合中返回一组数据的平均值。一切似乎都正常,除了答案是错误的,在一种情况下是 2 倍。
这是我的 Map/Reduce 函数 - 我不得不混淆 'diff' 值的来源,但从日志中返回的打印语句中我已验证其正确:
var mapFunction = function() {
if (this.fieldId==1234) {
print(diff);
}
emit(this.fieldId,diff);
};
var reduceFunction = function(keyId, viewTime) {
var count = viewTime.length;
var total = 0;
for (idx = 0; idx < viewTime.length; idx++) {
total+=viewTime[idx];
}
if (keyVidId==1234) {
print('1234: ' + total/count);
}
return total/count;
};
运行此程序后,对于特定记录 1234,我得到的结果大约是我从 MySQL 迁移之前得到的结果的两倍并且也是我使用之前使用的聚合框架得到的结果的两倍决定做 Map/Reduce 以实现可扩展性等。其他记录也是错误的,但一般不会那么多。
reduceFunction 最初使用 Array.avg,但我转换为手动平均值来尝试调试。
有问题的数据大约是 23,000 个文档,每个 diff 往往是一个非常大的整数。
我浏览了日志,试图找出问题所在,实际上使用 LibreOffice Calc 手动平均了日志中吐出的差异值,并得到了 正确 结果,因此错误在某处reduce 函数实现。
我注意到在日志中有多行显示“1234:”,就好像单个 keyId 多次调用 reduce 函数一样——我不太清楚它在下面是如何工作的,但我想它将工作负载分成多个函数调用,然后在最后组合,这意味着它必须对结果进行加权以获得正确的平均值……我想这可能是问题所在,但我不确定。我还担心它是 int32 溢出(因为所有差异的总和大于最大值),但在 python 中对相关数字进行一些修改似乎并非如此。
希望有人可以阐明 MongoDB 在后台做了什么以及我做错了什么......
谢谢!
【问题讨论】:
-
您能描述一下您的环境吗?使用复制?分片?
-
阅读 Map-Reduce 操作故障排除文档的这一部分:docs.mongodb.org/manual/applications/map-reduce/…
-
感谢 JohnnyHK,正是我想要的!没有看到那部分,并且完全可以理解reduce函数需要这样。如果其他人在进行平均时遇到类似的问题,我通过指定一个 finalize 函数来解决这个问题,该函数从 reduce 函数中获取一个总数和一个计数,以在最后生成最终平均值。