Mongoose Aggregation match an array of objectIds
Solution 1
To return all posts created by users depicted in a list of ids, use the $in
operator in your query and then chain the sort()
method to the query to order the results by the created date field:
Post.find({ "author": { "$in": userIds } })
.sort("-created") // or .sort({ field: 'asc', created: -1 });
.exec(function (err, data){
if(err){
return console.log(err);
} else {
return console.log(data);
}
});
To get a result where you have the post id's grouped per user, you need to run the following aggregation operation:
Post.aggregate([
{ "$match" : { "author": { "$in": userIds } } },
{ "$sort": { "created": -1 } },
{
"$group" : {
"_id" : "$author",
"posts" : { "$push": "$_id" }
}
},
{
"$project": {
"_id": 0,
"userId": "$_id",
"posts": 1
}
}
]).exec(function (err, result){
if(err){
return console.log(err);
} else {
return console.log(result);
}
});
Or with the fluent API:
Post.aggregate()
.match({ "author": { "$in": userIds } })
.sort("-created")
.group({
"_id" : "$author",
"posts" : { "$push": "$_id" }
})
.project({
"_id" : 0,
"userId" : "$_id",
"posts": 1
})
.exec(function (err, result){
if(err){
return console.log(err);
} else {
return console.log(result);
}
});
Solution 2
This should be possible without aggregation.
Post
.find({ author: { $in: userIds } })
.sort({ created: -1 })
If you get CastError: Cast to ObjectId failed, make sure to map your userIds array from an array of strings to an array of mongoose id's.
userIds = userIds.map(userId => new mongoose.Types.ObjectId(userId))
Related videos on Youtube
unwosu
Updated on September 20, 2022Comments
-
unwosu over 1 year
I have a schema that Looks like this
var Post = new mongoose.Schema({ author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, created: { type: Date, Default: Date.now })
I have a User Table as well. I Have a array of user ids and i am trying to search the post table based on an array of user ids
For Example
var userIds = ["575e96652473d2ab0ac51c1e","575e96652473d2ab0ac51c1d"] .... and so on
I want to return all posts created by these users. And posts should be sorted by their creation date. Is there a way to group this post based on the user ids provided, basically match the posts for an individual user?
The result I am trying to attain is something like this:
[{ userAId : "56656.....", post : [postA, postB], },{ userBId :"12345...", post : [postA, postB] }]
How do I write this query?
This is what I have so far
Post.aggregate([{ // {"$unwind" : ""}, // "$group": { // _id: "$author", // "created" : {"$sum" : 1 } // } "$match" : { author : id} }]).exec(function(error, data) { if(error){ return console.log(error); }else{ return console.log(data) } }) { "_id" : ObjectId("575e95bc2473d2ab0ac51c1b"), "lastMod" : ISODate("2016-06-13T11:15:08.950Z"), "author" : ObjectId("575dac62ec13010678fe41cd"), "created" : ISODate("2016-06-13T11:15:08.947Z"), "type" : "photo", "end" : null, "commentCount" : 0, "viewCount" : 0, "likes" : 0, "tags" : [], "title" : "Today is a good day", "__v" : 0 }
-
unwosu almost 8 yearsis there a way to group this post based on the user ids provided ?? basically match the posts for an individual user like this. {userAId : "56656", post : [{postA, postB}], userBId :"xys" , post : [postA,postB]}
-
unwosu almost 8 yearsIs there a way to group this post based on the user ids provided ?? basically match the posts for an individual user like this. {userAId : "56656", post : [{postA, postB}], userBId :"xys" , post : [postA,postB]}
-
unwosu almost 8 yearsWould it to be better to get the posts from the data base and do the concatenation in code ?
-
chridam almost 8 years@user3412942 Can you please update your question since the original problem I want to return all posts created by these users. And posts should be sorted by their creation date. How do i write this query? is solved, isn't it? Bear in mind that it's considered bad practice here on SO to change your question when there are answers already - chameleon questions.
-
unwosu almost 8 yearsI apologise I have updated the question thanks a lot for your support.
-
chridam almost 8 years@user3412942 I have updated my answer with the additional requirement
-
unwosu almost 8 yearsYou sir are a diamond this is just whatIi needed. Thats a lot for all the support and patience.