Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo aggregation framework, Sort and then group not working

I am trying sort data by date first and then group on another field. It is not working to me.

The question I am trying to answer is: Select the most recent distinct cid?

given this data:

db.summary.save({"lid" : 5, "date" : 5, "cid" : 2, "circles" : [ 2 ] })
db.summary.save({"lid" : 2, "date" : 2, "cid" : 1, "circles" : [ 2 ] })
db.summary.save({"lid" : 4, "date" : 0, "cid" : 3, "circles" : [ 2 ] })
db.summary.save({"lid" : 3, "date" : 3, "cid" : 2, "circles" : [ 2 ] })
db.summary.save({"lid" : 1, "date" : 1, "cid" : 1, "circles" : [ 2 ] })

db.summary.aggregate( {$match :{circles: 2}, $sort: {date: -1}, $group: {_id: '$cid'}} )

I am doing a match first on circles, then a sort on date, then a group on cid

The result I am getting:

{
    "result" : [
        {
            "_id" : 3
        },
        {
            "_id" : 1
        },
        {
            "_id" : 2
        }
    ],
    "ok" : 1
}

Here is my analysis:

before matching or sorting by date, the data was:

"lid" : 5, "date" : 5, "cid" : 2
"lid" : 2, "date" : 2, "cid" : 1
"lid" : 4, "date" : 0, "cid" : 3
"lid" : 3, "date" : 3, "cid" : 2
"lid" : 1, "date" : 1, "cid" : 1

After sorting by date, the data set would be:

"lid" : 5, "date" : 5, "cid" : 2
"lid" : 3, "date" : 3, "cid" : 2
"lid" : 2, "date" : 2, "cid" : 1 
"lid" : 1, "date" : 1, "cid" : 1
"lid" : 4, "date" : 0, "cid" : 3

So after grouping, the result I expect is:

{
    "result" : [
        {
            "_id" : 2
        },
        {
            "_id" : 1
        },
        {
            "_id" : 3
        }
    ],
    "ok" : 1
}

What query does solve my problem?

Why is the current query not working for me?

like image 471
ben39 Avatar asked Jan 25 '13 00:01

ben39


People also ask

How do I sort data in MongoDB aggregation?

In MongoDB, the $sort stage is used to sort all the documents in the aggregation pipeline and pass a sorted order to the next stage of the pipeline. Lets take a closer look at the above syntax: The $sort stage accepts a document that defines the field or fields that will be used for sorting.

How do I sort groups in MongoDB?

And for group sorting in MongoDB, the $group operator is used with the $sort operator. With the help of the $group and $sort operator, MongoDB can also sort the grouped data in ascending or descending order. In this post, we have provided an informative insight into the aggregate group sort functionality of MongoDB.

Does MongoDB support sorting?

MongoDB can perform sort operations on a single-field index in ascending or descending order. In compound indexes, the sort order determines whether the index can be sorted.

Which aggregation method is preferred for use by MongoDB?

The pipeline provides efficient data aggregation using native operations within MongoDB, and is the preferred method for data aggregation in MongoDB. The aggregation pipeline can operate on a sharded collection. The aggregation pipeline can use indexes to improve its performance during some of its stages.


1 Answers

When you $group after a $sort in the pipeline, the previous sort is lost. You'd have to do something like this instead so that the date you want to sort by is available after the grouping:

db.summary.aggregate(
    {$match: {circles: 2}},
    {$group: {_id: '$cid', date: {$max: '$date'}}},
    {$sort: {date: -1}});

result:

[ { _id: 2, date: 5 }, 
  { _id: 1, date: 2 }, 
  { _id: 3, date: 0 } ]

Add a $project to the end of the pipeline if you want to reshape the output.

like image 52
JohnnyHK Avatar answered Sep 21 '22 15:09

JohnnyHK