Sort and Group in one MongoDB aggregation query Sort and Group in one MongoDB aggregation query mongoose mongoose

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}