Question

with this code:

var map = function(){

    emit(1, { read: this.read, important: this.important, count: 1 })
}

var reduce = function(key, vals) {

    var i = 0, r = 0, c = 0;

    vals.forEach(function(d) {
       r += !d.read ? 0 : 1;
       i += d.important ? 0 : 1
       c += d.count;
    });

    return { read: r, important: i, count: c }
}

db.ipdr.mapReduce(map, reduce, { out: "__mr_test", verbose: true, query: { liid: "40001" } });
db.getCollection("__mr_test").find();

I get incomplete count:

{
    "_id" : 1,
    "value" : {
        "read" : 1,
        "important" : 7,
        "count" : 7607
    }
}

"count" is OK, but "read" and "important" should be a lot higher. Am I missing something?

Was it helpful?

Solution

This is not a good usage of mapReduce. The aggregation framework uses native code which is much faster than JavaScript execution and can do the same job. Assuming "read" and "important" are logical values that is:

db.posts.aggregate([
    { "$sort": { "read": 1, "important": 1 } },
    { "$group": {
        "_id": null,
        "read": { "$sum": { "$cond": [ "$read", 1, 0 ] } },
        "important": { "$sum": { "$cond": [ "$important", 1, 0 ] } },
        "count": { "$sum": 1 }
    }}
])

So not only faster but much more simple to code.

Given the sample documents:

{ "read" : true,  "important" : false }
{ "read" : true,  "important" : false }
{ "read" : false, "important" : false }
{ "read" : false, "important" : true  }
{ "read" : true,  "important" : true  }

The result would be:

{ "_id" : null, "read" : 3, "important" : 2, "count" : 5 }

OTHER TIPS

Instead of

r += !d.read ? 0 : 1;
i += d.important ? 0 : 1
c += d.count;

Shouldn't you be having

r += !d.read ? 0 : d.read;
i += d.important ? 0 : 1
c += d.count;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top