令人费解的两个看似相同的MapReduce函数的行为

时间:2012-05-23 16:38:48

标签: javascript mongodb mapreduce

我们的MongoDB数据库包含所有用户帐户的列表,其中每个新注册在帐户文档中都有一个“created_at”字段,其中包含创建时的当前日期和时间。

我们希望了解有多少新注册或每天注册,因此请将MapReduce查询放在一起以便为我们找到。

db.accounts.mapReduce(
    function() { 
        var date = this.created_at.toLocaleDateString(); 
        emit(date, 1);
    }, 
    function(key, values) {
        return values.length;
    },
    { out: "output" })

我们的第一次尝试就在上面。对于每次注册,它会为该日期发出1的值。然后使用每个数组的长度来确定当天注册的数量。

然而,尽管结果大多是正确的,但仍有明显的不准确之处。例如,当我们知道实际数字远高于第一天时,我们给出了一个双数值。在第二次运行map reduce函数后,有些值发生了变化,尽管对相同的数据进行了操作。

我们将函数更改为总结数组的值(记住,应该只包含1,因此与array.length相同。

db.accounts.mapReduce(
    function() {
        var date = this.created_at.toLocaleDateString(); 
        emit(date, 1);
    }, 
    function(key, values) {
        var sum = 0; 
        for(var i = 0; i < values.length; i++) { 
            sum += values[i];
        }; 
        return sum; 
    },
    { out: "output" })

令我们惊讶的是,这给出了之前错误的每个日期的正确结果。

有谁知道为什么第一张地图缩小版没有按预期运作?

1 个答案:

答案 0 :(得分:2)

对于发出的值,可以多次调用Reduce,稍后的调用将传递给reduce的先前调用的输出。当您只查看数组的长度时,您会错过可能正在查看部分聚合数据的事实。对这些值求和将使早期的聚合累积,这就是你想要的。