我是MongoDB的初学者,我只是想知道MongoDB在Map-Reduce中的Finalize函数/步骤的功能是什么。我们在finalize()函数中所做的一切实际上都可以在reduce函数中完成。我只是想知道是什么迫使我们使用finalize。我对此进行了研究,一无所获。非常感谢帮助我
答案 0 :(得分:11)
虽然我知道这个问题在3年前被问及回答,但我有同样的问题,并认为未来的googlers可能会发现此附加信息有用:reduce()
可能被称为multiple times,密钥相同,传递给它的一些值是先前reduce()
次调用返回的值。这可能是因为集合未按相关密钥排序,incremental Map-Reduce,parallel execution等。这就是为什么reduce()
应始终返回相同类型的值的原因例如,emit()
传递给map()
。
因此,假设您的map
函数只为每个文档发出一个数字,并使用reduce
函数计算每个键的总和和平均值:
function reduce(key, values) {
var resultObj = {
sum: Array.sum(values)
};
resultObj.average = result.sum / values.length;
return resultObj;
}
在这种情况下,如果传递包含resultObj
的数组,则代码将会出错,因为我不确定Array.sum()
传递数字和对象的对象时会发生什么。即使这不是问题,此代码也会忽略之前计算的任何平均值并返回不正确的结果。
finalize()
只被调用一次,因此它可以返回它想要的任何东西,并且(如接受的答案所提到的)它在所有数据被处理之后运行。因此,要正确执行上述操作,而不是在映射阶段仅发出一个数字,您将发出类似{ sum: myVal, count: 1 }
的内容。然后你的reduce
函数将是:
function reduce(key, values) {
var resultObj = {
sum: 0,
count: 0
};
for (var i in values) {
resultObj.sum = resultObj.sum + values[i].sum;
resultObj.count = resultObj.count + values[i].count;
}
return resultObj;
}
...最后你可以计算finalize
中的平均值:
function finalize(key, reducedValue) {
return {
sum: reducedValue.sum,
average: reducedValue.sum / reducedValue.count
};
}
答案 1 :(得分:5)
最大的原因之一是在最终数据集完成所有内容后运行finalize。不仅如此,最终确定也可以在单个结果上运行,而减少将跳过单个结果。
如果您可以使用reduce执行所有操作,则使用reduce,您无需进行最终确定。