根据条件计算MapReduce中的文档 - MongoDB

时间:2012-11-27 09:12:52

标签: mongodb mapreduce

我正在尝试使用Map Reduce根据每个日期的某个字段值来计算数字文档。首先,这是一些常规find()函数的结果:

db.errors.find({ "cDate" : ISODate("2012-11-20T00:00:00Z") }).count();

返回579(即此日期有579份文件)

db.errors.find( { $and: [ { "cDate" : ISODate("2012-11-20T00:00:00Z") }, {"Type":"General"} ] } ).count()

返回443(即,此日期有443份文件,其中Type =“General”)

以下是我的MapReduce:

db.runCommand({ mapreduce: "errors", 
 map : function Map() {
    emit(
        this.cDate,//Holds a date value
        {
        count: 1,
        countGeneral: 1,
        Type: this.Type 
        }
    );
},

reduce : function Reduce(key, values) {
    var reduced = {count:0,countGeneral:0,Type:''};

    values.forEach(function(val) {
        reduced.count += val.count; 
        if (val.Type === 'General')
            reduced.countGeneral += val.countGeneral;
    });

return reduced; 
},

finalize : function Finalize(key, reduced) {
    return reduced;
},

query : { "cDate" : { "$gte" : ISODate("2012-11-20T00:00:00Z") } },

out : { inline : 1 }
});

对于日期20-11-20,地图减少了回报:

count: 579

countGeneral: 60 (should be 443 according to the above find query)

现在,我知道Reduce在循环方式上是不可预测的,所以我应该怎么做? 谢谢

2 个答案:

答案 0 :(得分:1)

我建议你丢失其余的价值只是因为你没有在减少部分返回'一般'。

对于map部分中发出并从reduce函数返回的所有值,Reduce运行多次。

例如,当reduce的第一次迭代运行时,你的输出对象包含如下内容:

{count: 15, countGeneral: 3, Type: ''}

还有其他的reduce迭代会收集这个对象和其他像这样的对象,并且不会在那里看到Type:'General'并且不再增加countGeneral

答案 1 :(得分:0)

您的地图功能有误。 你可以这样做:

function Map() {
    var cG=0;
    if (this.Type == 'General') { cG=1; }
    emit(
        this.cDate,//Holds a date value
        {
        count: 1,
        countGeneral: cG
        }
    );
}

如果Type为'General',则发出countGeneral 1,否则为0。

然后你可以完全从你的emit函数中删除类型检查,因为你无论如何都要在reduce函数中销毁它。目前你的reduce clobbers在reduce阶段输入从emit传递的信息。