Mongoose Aggregation match an array of objectIds

14,118

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))

Share:
14,118

Related videos on Youtube

unwosu
Author by

unwosu

Updated on September 20, 2022

Comments

  • unwosu
    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
    unwosu almost 8 years
    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 :"xys" , post : [postA,postB]}
  • unwosu
    unwosu almost 8 years
    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 :"xys" , post : [postA,postB]}
  • unwosu
    unwosu almost 8 years
    Would it to be better to get the posts from the data base and do the concatenation in code ?
  • chridam
    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
    unwosu almost 8 years
    I apologise I have updated the question thanks a lot for your support.
  • chridam
    chridam almost 8 years
    @user3412942 I have updated my answer with the additional requirement
  • unwosu
    unwosu almost 8 years
    You sir are a diamond this is just whatIi needed. Thats a lot for all the support and patience.