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
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.
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.
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.
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"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With