Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregating by a field and selecting the document with the max value of another field as a collection

Tags:

mongodb

Using the aggregate framework, what is the best way to get documents with a maximum value of a field per grouping so using the collection below I would like to have functionality to return one document for each group_id having the latest date. The second listing shows the desired result.

group_id date 
1        11/1/12  
1        11/2/12
1        11/3/12
2        11/1/12
3        11/2/12
3        11/3/12

DESIRED RESULT

group_id date
1        11/3/12
2        11/1/12
3        11/3/12
like image 891
user1795267 Avatar asked Nov 02 '12 21:11

user1795267


People also ask

Which is used in aggregate method in Mongodb?

Map Reduce. Map reduce is used for aggregating results for the large volume of data. Map reduce has two main functions one is a map that groups all the documents and the second one is the reduce which performs operation on the grouped data.

What does aggregate do in mongoose?

Mongoose's aggregate() function returns an instance of Mongoose's Aggregate class. Aggregate instances are thenable, so you can use them with await and promise chaining. The Aggregate class also supports a chaining interface for building aggregation pipelines.

Is aggregate faster than find in Mongodb?

Because of this, if you have a simple aggregation pipeline or one which does not cut down the data volume much it can often be quicker to use a find() and perform the aggregation client side.


1 Answers

You can use the $max grouping function in the Aggregation Framework to find the latest document for each group_id. You will need additional queries to retrieve the full documents based on the grouped criteria.

var results = new Array();
db.groups.aggregate(
    // Find documents with latest date for each group_id
    { $group: {
        _id: '$group_id',
        date: { $max: '$date' },
    }},
    // Rename _id to group_id, so can use as find criteria
    { $project: {
        _id: 0,
        group_id:'$_id',
        date: '$date'
    }}
).result.forEach(function(match) {
    // Find matching documents per group and push onto results array
    results.push(db.groups.findOne(match));
});

Example results:

{
    "_id" : ObjectId("5096cfb8c24a6fd1a8b68551"),
    "group_id" : 1,
    "date" : ISODate("2012-11-03T00:00:00Z"),
    "foo" : "bar"
}
{
    "_id" : ObjectId("5096cfccc24a6fd1a8b68552"),
    "group_id" : 2,
    "date" : ISODate("2012-11-01T00:00:00Z"),
    "foo" : "baz"
}
{
    "_id" : ObjectId("5096cfddc24a6fd1a8b68553"),
    "group_id" : 3,
    "date" : ISODate("2012-11-03T00:00:00Z"),
    "foo" : "bat"
}
like image 196
Stennie Avatar answered Oct 07 '22 22:10

Stennie