完成MongoDB Map-Reduce中的步骤

时间:2014-07-19 01:18:31

标签: mongodb mapreduce

我是MongoDB的初学者,我只是想知道MongoDB在Map-Reduce中的Finalize函数/步骤的功能是什么。我们在finalize()函数中所做的一切实际上都可以在reduce函数中完成。我只是想知道是什么迫使我们使用finalize。我对此进行了研究,一无所获。非常感谢帮助我

2 个答案:

答案 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,您无需进行最终确定。