Rodrigo Dias Rodrigo Dias - 2 months ago 14
Ruby Question

mongodb count equal object

I have a MongoDB database with documents that contain a filter field. The documents looks like this:

{
"_id": ObjectId("503208f5b5db0135387d9249"),
"name": "name1",
"filter": "facebook"
} {
"_id": ObjectId("503208f5b5db0135387d9249"),
"name": "name2",
"filter": "twitter"
}
{
"_id": ObjectId("503208f5b5db0135387d9249"),
"name": "name3",
"filter": "twitter"
}


And I want to count by type. This example should be like this:

facebook => 1, twitter => 2


With ruby code, counting is very slow.

The filter is a String which could be anything. E.g:

{facebook : 1203, twitter : 201, wherever : 200, othertype : 400}


I am using mongo mapper (ruby driver).

==============
EDIT 3

Finally it's working. here's the code for ruby driver:

def map
'function(){
emit(this.plataforma, 1);
}'
end
def reduce
'
function(prev, current) {
var n = 0;
current.forEach(function(v){
n+=v;
});
return n;
}'
end

def build
Mention.collection.map_reduce(map, reduce, :query => {})
end

Answer Source

This is similar to: http://cookbook.mongodb.org/patterns/count_tags/

Where by it shows how you could run an MR like so:

var map = function(){
    emit(this.filter,1);
}

var reduce  = function(previous,current){
    var count = 0;

    for (index in current) {
        count += current[index];
    }

    return count;
}

Which will then output, to another collection (or inline if you want) documents of the format:

{
    _id: facebook,
    value: 1,
    _id: twitter,
    value: 2
}

This is written in MongoDBs console language which is JS. MongoDB has a built in JavaScript parser (spidermonkey) which can parse MR functions. From Ruby you would encapsulate your functions like so:

map = BSON::Code.new "function() { emit(this.filter, 1); }"

And then run the MR like so:

col.map_reduce(map, reduce,
        {
            :out => 'summary_collection',
            :raw => true
        }
      )

And then you would just query summary collection for that filter by supplying the string representation as the _id or do a simple find() to get all results.