views:

116

answers:

2

Hi folks,

This is my table:

unicorns =  {'name':'George',
             'actions':[{'action':'jump', 'time':123123}, 
                        {'action':'run', 'time':345345}, 
                        ...]}

How can I perform the following queries?

  • Grab the time of all actions of all unicorns where action=='jump' ?

  • Grab all actions of all unicorns where time is equal?

    e.g. {'action':'jump', 'time':123} and {'action':'stomp', 'time':123}


Help would be amazing =)

+2  A: 

Use dot-separated notation:

db.unicorns.find({'actions.action' : 'jump'})

Similarly for times:

db.unicorns.find({'actions.time' : 123})

Edit: if you want to group the results by time, you'll have to use MapReduce.

kristina
Second query seems to choose all unicorns with `action.time==123`. I may be wrong here, but I understood that the question was about result like `{12345: [{'action': 'jump', 'time': 12345}, {'action': 'stomp', 'time': 12345}], 12390: [{'action': 'jump', 'time': 12390}, {'action': 'run', 'time': 12390}]}`... but maybe I'm wrong :)
viraptor
@kristina: thanks for the reply!! =) For the second query, I was asking more for grouping up actions by time, should express myself better. Thanks again!
RadiantHex
+2  A: 

For the second query, you need to use MapReduce, which can get a big hairy. This will work:

map = function() {
    for (var i = 0, j = this.actions.length; i < j; i++) {
        emit(this.actions[i].time, this.actions[i].action);
    }
}
reduce = function(key, value_array) {
    var array = [];
    for (var i = 0, j = value_array.length; i < j; i++) {
        if (value_array[i]['actions']) {
            array = array.concat(value_array[i]['actions']);
        } else {
            array.push(value_array[i]);
        }
    }
    return ({ actions: array });
}

res = db.test.mapReduce(map, reduce)
db[res.result].find()

This would return something like this, where the _id keys are your timestamps:

{ "_id" : 123, "value" : { "actions" : [ "jump" ] } }
{ "_id" : 125, "value" : { "actions" : [ "neigh", "canter" ] } }
{ "_id" : 127, "value" : { "actions" : [ "whinny" ] } }

Unfortunately, mongo doesn't currently support returning an array from a reduce function, thus necessitating the silly {actions: [...]} syntax.

Emily
@Emily: woah thanks Emily! Thanks for pointing me into this direction, and thanks for that MapReduce function!! I'm on it right now!! =)
RadiantHex