两个看似相同的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" })

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

有谁知道为什么第一次地图缩减没有按预期运行?

对于发出的值,可以多次调用Reduce,以后的调用将传递到早期调用的输出以进行reduce。 当您只查看数组的长度时,您会忽略可能正在查看部分聚合数据的事实。 对值求和将使较早的聚合累积,这是您想要的。

相关内容

  • 没有找到相关文章

最新更新