Reputation: 24583
I have the following aggregate:
db.reports.aggregate({ $group: { _id: "$user", reports: { $push: {report: {properties: "$properties"} } }}}, { $project: { _id: 0, user: "$_id", reports: "$reports"} })
I would like to somehow limit the number of reports that get pushed into the array. I.E I want to limit reports to a users defined value. 1,5,10 etc. Meaning I want N number of reports (I will sort by timestamp) to be included in the reports field. Right now I am pushing all reports not sure how to limit the number of reports per user.
I tried the $limit, but that didn't work as it restricted the number of users returned not the number of reports pushed into the reports array.
Basically I want to group my reports by user, and include only a certain number of reports. I would like to limit the number of reports as early as possible such that I do not have to deal with the entire collection throughout the pipeline
Upvotes: 1
Views: 1313
Reputation: 936
Have you looked into using group()? Let's say your data looks like this:
{ "_id" : ObjectId("732"), "user" : "john", "reports" : [ "report1", "report2", "report3" ] }
{ "_id" : ObjectId("733"), "user" : "john", "reports" : [ "report4", "report5", "report6" ] }
{ "_id" : ObjectId("734"), "user" : "max", "reports" : [ "report1", "report2", "report3" ] }
{ "_id" : ObjectId("735"), "user" : "max", "reports" : [ "report4" ] }
{ "_id" : ObjectId("736"), "user" : "eliza", "reports" : [ "report1", "report2" ] }
Assuming reports is an array in the initial schema, your aggregation call becomes:
var reduce_f = function(curr, result) {
result.reports = result.reports.concat(curr.reports);
};
var finalize_f = function(result) {
var limit = 5;
result.reports = result.reports.slice(0, limit);
};
db.reports.group({
key: { user: 1 },
reduce: reduce_f,
initial: { reports : [] },
finalize: finalize_f
})
Note that group will not work in a sharded environment.
Upvotes: 2