Counting documents in MapReduce depending on condition - MongoDB

老子叫甜甜 提交于 2019-12-13 03:06:33

问题


I am trying to use a Map Reduce to count number documents according to one of the field values per date. First, here are the results from a couple of regular find() functions:

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

returns 579 (ie. there are 579 documents for this date)

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

returns 443 (ie. there are 443 documents for this date where Type="General")

Following is my 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 }
});

For the date 20-11-20 the map reduce returns:

count: 579

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

Now, I understand that the Reduce is unpredictable in the way it loops so how should I do this? Thanks


回答1:


Your map function is wrong. You could do something like this:

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

This emits countGeneral 1 if Type is 'General' and 0 otherwise.

Then you can remove the type check from your emit function entirely, since you're destroying it anyway in your reduce function. Currently your reduce clobbers Type information passed from emit during the reduce phase.




回答2:


I suggest that you lose the rest of your values just because you don't return 'General' in your reduce part.

Reduce runs more than once for all the values emitted in the map part and returned from the reduce function.

For example, when the first iteration of reduce have run, you've got output object containing something like:

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

And other iterations of reduce collect this object and others like this one and don't see Type:'General' there and don't increase the countGeneral anymore.



来源:https://stackoverflow.com/questions/13580755/counting-documents-in-mapreduce-depending-on-condition-mongodb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!