The data you are working with looks like it has come as the output of a mapReduce operation already, since it has that specific "_id" and "value" structure that mapReduce prodcues. As such you may be better off going back to the logic of how that process is implemented and follow the same to just extract and total what you want, or at least change it's output form to this:
{ _id: { evt: "click", val: { "type": "default", "x": "125", "y": "311", "time": "1" } }, value: { count: 1 } }, { _id: { evt: "click", val: { "type": "default", "x": "154", "y": "321", "time": "2" } }, value: { count: 2 } }, { _id: { evt: "click", val: { "type": "default", "x": "192", "y": "263", "time": "1" } }, value: { count: 4 } }
As the problem is that the aggregation framework "presently" lacks the ability to address the "indexed" position of an array ( real "non-associative" array and not PHP array ) and would always return null when you try to do so.
Lacking the ability to go back to the original source or mapReduce operation, then you can write a mapReduce operation on this data to get the expected results ( shell representation since it's going to be a JavaScript anyway ):
db.collection.mapReduce( function() { emit({ evt: this._id.evt, time: this._id.val[3] }, this.value.count) }, function(key,values) { return Array.sum(values) }, { out: { inline: 1 } } )
Which returns typical mapReduce output like this:
{ "_id" : { "evt" : "click", "time" : "1" }, "value" : 5 }, { "_id" : { "evt" : "click", "time" : "2" }, "value" : 2 }
If you were able to at least transform the current output collection to the form suggested at first above, then you would run with the aggregation framework like this instead ( again common representaion ):
{ "$group": { "_id": { "evt": "$_id.evt", "time": "$_id.val.time" }, "count": { "$sum": "$value.count" } }}
Which of course would yield from the altered data:
{ "_id" : { "evt" : "click", "time" : "2" }, "count" : 2 } { "_id" : { "evt" : "click", "time" : "1" }, "count" : 5 }
In future releases of MongoDB, there will be a $slice operator which allows the array handling, so with your current structure you could do this instead:
{ "$group": { "_id": { "evt": "$_id.evt", "time": { "$slice": [ "$_id.val", 3,1 ] } }, "count": { "$sum": "$value.count" } }}
Which allows picking of the "third" index element from the array, albeit that this will of course still return an "array" as the element like this:
{ "_id" : { "evt" : "click", "time" : [ "2" ] }, "count" : 2 } { "_id" : { "evt" : "click", "time" : [ "1" ] }, "count" : 5 }
So right now, if you can change your initial mapReduce output then do it. Either to the form as shown here or just work with modifications to the initial query to get the end result you want here. Modifying to the recommened form will at least allow the .aggregate() command to work as is shown in the second example here.
If not, then mapReduce is still the only way at present for writing, as shown in the "first" example.