user3412942 user3412942 - 5 months ago 257
Node.js Question

Mongoose Aggregation match an array of objectIds

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. 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
}


The result i am trying to attain is something like this, sorry for the confusion earlier.

Is 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 :"12345...",
post : [postA,postB]
}]

Answer

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(error){
            return console.log(error);
        } 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(error){
        return console.log(error);
    } 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(error){
            return console.log(error);
        } else {
            return console.log(result);
        }
    });
Comments