我在 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 手动平均了日志中吐出的 diff 值并得到了正确的结果,因此错误出现在 reduce 函数实现中。
我注意到在日志中有多行显示“1234:”,就好像单个keyId多次调用reduce函数一样-我不太清楚它在下面是如何工作的,但我想它会拆分将工作负载转换为多个函数调用,然后在最后组合,这意味着它必须对结果进行加权以获得正确的平均值……我想这可能是问题所在,但我不确定。我也担心它是一个 int32 溢出(因为所有差异的总和大于最大值),但在 python 中对有问题的数字进行一些修改似乎并非如此。
希望有人可以阐明MongoDB在后台做什么以及我做错了什么......
谢谢!