Mongoose aggregate into a nested doc Get count and append new value to the query result

Viewed 99

I have this users and posts collection with embedded docs comments and replies:

  1. users
{
 _id:34
 name:"dimer"
}
  1. Posts
{
 _id:"1234",
 body:" hello ! I love mongodb, but its hard",
 likes:["34"],
 comments:{
    _id:"3453",
    body:"me I don't like mongodb i like sql "
    likes:["34"],
    replies:{
       _id:"2345",
       body:"both of them are great"
       likes:["34"],
    }
  }
}

The question is that, i want to aggregate into the posts and get all the them, after that i want to append new key value to both post, comments, replies, witch gonna specify if the user liked the post or not ex: liked:true Note: I have the authenticated user id ready . I want check if the user Id exist in the likes docs on each sub trees (posts, comments, replies )

To be more specific about this question this is my expected humble result :

{
 _id:"1234",
 body:" hello ! I love mongodb, but its hard",
 liked:true,
 likesCount:1
 comments:{
     _id:"3453",
     body:"me I don't like mongodb i like sql "
     liked:true,
     likesCount:1
     replies:{
       _id:"2345",
       body:"both of them are great"
       liked:true,
       likesCount:1
    }
  }
}

Note : If you can help to query upto the comments its okay for me : Result expected :

{
 _id:"1234",
 body:" hello ! I love mongodb, but its hard",
 liked:true,
 likesCount:1
 comments:{
     _id:"3453",
     body:"me I don't like mongodb i like sql "
     liked:true,
     likesCount:1
  }
}

This is what I tried this, not working at all :

const result = await PostModel.aggregate([
      {
        $project: {
          likesCount: { $size: "$likes" },
          commentsCount: { $size: "$comments" },
          liked: { $in: [ID(uid), "$likes"] },
          likes: 1,
          comments:{
             likesCount: { $size: "$likes" },
             liked: { $in: [ID(uid), "$likes"] },
            ......
         } 
     }
}

... Note : i want to use $group and $unwind to find a much cleaner solution my fake solution

1 Answers

According to your first expected result, this is a solution

const result = await PostModel.aggregate([
{
      $project: {
          _id: 1,
          body: 1,
          liked: { $in: [ID(uid), "$likes"] },
          likesCount: { $size: "$likes" },
          comments: {
                _id: 1,
                body:1,
                liked: { $in: [ID(uid), "$comment.likes"] },
                likesCount: { $size: "$comment.location.likes" },
               
      }
}]);

by this query, you will get response like this -

{
"_id" : "1234",
"body" : " hello ! I love mongodb, but its hard",
"liked" : true,
"likesCount" : 1
"comments" : {
    "_id" : 3453",
    "body" : "me I don't like mongodb i like sql ",
    "liked" : true,
    "likesCount" : 1
    "replies" : {
        "_id" : "2345",
        "body" : "both of them are great",
        "liked" : true,
        "likesCount" : 1
    },
}}

And if you want second expected result then this is a solution -

const result = await PostModel.aggregate([
{
      $project: {
          _id: 1,
          body: 1,
          liked: { $in: [ID(uid), "$likes"] },
          likesCount: { $size: "$likes" },
          comments: {
                _id: 1,
                body:1,
                liked: { $in: [ID(uid), "$likes"] },
                likesCount: { $size: "$likes" },
              }
      }
}])

And expected result by this -

{
"_id" : "1234",
"body" : " hello ! I love mongodb, but its hard",
"liked" : true,
"likesCount" : 1
"comments" : {
    "_id" : "3453",
    "body" : "me I don't like mongodb i like sql ",
    "liked" : true,
    "likesCount" : 1
}}
Related