Sort and Group in one MongoDB aggregation query
You need to first $group
and $sort
the result. Since you only want the _id
field you will need the $project
stage.
db.test.aggregate( [ { "$group": { "_id": "$category" }}, { "$sort" : { "ts": 1 }}, { "$project": { "_id": 1 }} ]);
If you want to sort the other way, do it like this:
db.test.aggregate([{ $sort : {ts: -1}},{ $group:{"_id":"$category"}}]);
Notice the -
in front of the 1.
When you first $sort
by ts
, you are basically sorting all the elements from your collection. Thus, if you were to only run the $sort
stage in the aggregation pipeline, you would get the following result:
//Querydb.test.aggregate([ { $sort: { ts: 1} }]);//Output{ "_id" : ObjectId("55141da6e4c260ae9e00832b"), "ts" : 40, "category" : 3 }{ "_id" : ObjectId("55141d9fe4c260ae9e00832a"), "ts" : 60, "category" : 2 }{ "_id" : ObjectId("55141d99e4c260ae9e008329"), "ts" : 80, "category" : 1 }{ "_id" : ObjectId("55141d93e4c260ae9e008328"), "ts" : 100, "category" : 1 }
In your code, when you add the $group
stage, you are basically grouping the above results by the category
field, producing the output that you get:
{ "_id" : 1 }{ "_id" : 2 }{ "_id" : 3 }
In the end it all depends on what you are trying to achieve.
If you want to return the categories filtered by the ts
field, you should only use the $sort
stage and then manipulate the resulting data set:
var data = db.test.aggregate([ {$sort: { ts: 1}}, {$project: { _id: 0, ts: 1, category: 1 } }]).toArray();for(var i = 0; i < data.length; i++) { console.log(data[i].category); //Output 3, 2, 1 in that sequence, on different lines}