Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB Map Reduce - Finalize to skip some results

I have a map reduce function that works on a collection as follows:

function Map() {
    emit (
        this.name, 
        { 
            count : 1,
            flag : this.flag

        }
    );
}
function Reduce(key, values) {
    var count = 0;
    var flag = false;

    for (var i in values){
        count = count + 1;
        if (i.flag)
             flag = true;
    }

    var reduced = {
        count : count,
        flag  : flag
    }
    return reduced;
}
function Finalize(key, reduced) {

    if (reduced.count>10 || reduced.flag){
        var finalized = {
            "count" : reduced.count 
        }
        return reduced;
    }

    return null;
}

What I am trying to do is that the Finalize will only return objects that pass a certain threshold (e.g. count>10). Currently it is still returning objects and the count is just null.

Any ideas?

like image 358
checklist Avatar asked Aug 05 '13 15:08

checklist


2 Answers

I would suggest you use the aggregation framework instead as it's much faster and easier to understand. Your above M/R/F can be written as easily as:

db.so.insert( { name: "Derick" } );
db.so.insert( { name: "Derick" } );
db.so.insert( { name: "Derick" } );
db.so.insert( { name: "Derick" } );
db.so.insert( { name: "Checklist" } );
db.so.insert( { name: "Checklist" } );
db.so.insert( { name: "Whoop" } );
db.so.insert( { name: "Whoop", flagged: true } );
db.so.aggregate( [
    { $group: { 
        _id: '$name', 
        count: { $sum: 1 }, 
        flagged: { $sum: 
            { $cond: [ { $eq: [ '$flagged', true ] }, 1, 0 ] } 
        } 
    } },
    { $match: { $or: [ { count: { $gt: 3 } }, { flagged: { $gt: 0 } } ] } }
] );

Which returns:

{
    "result" : [
        {
            "_id" : "Whoop",
            "count" : 2,
            "flagged" : 1
        },
        {
            "_id" : "Derick",
            "count" : 4,
            "flagged" : 0
        }
    ],
    "ok" : 1
}
like image 127
Derick Avatar answered Nov 07 '22 08:11

Derick


You can't.
Finalize will can only change the format of your value, but you cannot cancel out the key (which is actually dictated by the map phase emits).

like image 32
igorludi Avatar answered Nov 07 '22 09:11

igorludi