Search code examples
node.jsmongodbmongoose

mongoose query - How to fetch other collection based on current lookup id and insert it into current lookup?


I have 3 collections (User, Post, Comment), with their schema like this:

User

{
  fullName: String,
  email: String,
}

Post

{
  author: {type: mongoose.Schema.Types.ObjectId, required: true},
  description: String
  //other property not really usefull
}

Comment

{
  postId: {type: mongoose.Schema.Types.ObjectId, required: true},
  user: {type: mongoose.Schema.Types.ObjectId, required: true},
  value: {type: String, required: true},
}

I want to fetch a post with comment and user detail of each commentator, but i have problem how to push user into comment scope, anyone can help me how to achieve my expected result?

here i have create a playground of my current result at https://mongoplayground.net/p/_sBRbsTfl6i

Please ignore if ObjectId is not consistent

Expected result:

also if possible get result as Object instead of Array without Array[0]

[
  {
    "_id": ObjectId("3417dc3a09ce612aa858b627"),
    "author": ObjectId("5f17dc2309ce612aa858b625"),
    "description": "Post 1",
    "imageUrl": "http://localhost:8080/post/Flix-1705251483897.png",
    "comments": [
      {
        "_id": ObjectId("65a4131b395df50b87af7351"),
        "postId": ObjectId("3417dc3a09ce612aa858b627"),
        "user": {
          "_id": ObjectId("5f17dc2309ce612aa858b625"),
          "email": "[email protected]",
          "fullName": "Flix"
        },
        "value": "Gw comment nih"
      },
      {
        "_id": ObjectId("65a4153a51366ff44b4fa006"),
        "postId": ObjectId("3417dc3a09ce612aa858b627"),
        "user": {
          "_id": ObjectId("5f17dc2309ce612aa858b625"),
          "email": "[email protected]",
          "fullName": "Flix"
        },
        "value": "Eh ketinggalan comment ini"
      },
      {
        "_id": ObjectId("65a41f168b74183c4922aa42"),
        "postId": ObjectId("3417dc3a09ce612aa858b627"),
        "user": {
          "_id": ObjectId("5f17dc2309ce612aa858b123"),
          "email": "[email protected]",
          "fullName": "Wakwaw"
        },
        "value": "Comment gw nih 123"
      }
    ]
  }
]

Current result:

[
  {
    "_id": ObjectId("3417dc3a09ce612aa858b627"),
    "author": ObjectId("5f17dc2309ce612aa858b625"),
    "description": "Post 1",
    "imageUrl": "http://localhost:8080/post/Flix-1705251483897.png",
    "comments": [
      {
        "_id": ObjectId("65a4131b395df50b87af7351"),
        "postId": ObjectId("3417dc3a09ce612aa858b627"),
        "user": ObjectId("5f17dc2309ce612aa858b625"),
        "value": "Gw comment nih"
      },
      {
        "_id": ObjectId("65a4153a51366ff44b4fa006"),
        "postId": ObjectId("3417dc3a09ce612aa858b627"),
        "user": "5f17dc2309ce612aa858b625",
        "value": "Eh ketinggalan comment ini"
      },
      {
        "_id": ObjectId("65a41f168b74183c4922aa42"),
        "postId": ObjectId("3417dc3a09ce612aa858b627"),
        "user": ObjectId("5f17dc2309ce612aa858b123"),
        "value": "Comment gw nih 123"
      }
    ],
    "user": [
      {
        "_id": ObjectId("5f17dc2309ce612aa858b123"),
        "email": "[email protected]",
        "fullName": "Wakwaw"
      },
      {
        "_id": ObjectId("5f17dc2309ce612aa858b625"),
        "email": "[email protected]",
        "fullName": "Flix"
      }
    ]
  }
]

Solution

  • Simply perform the $lookup to users collection in the sub-pipeline.

    db.posts.aggregate([
      {
        $match: {
          _id: ObjectId("3417dc3a09ce612aa858b627")
        }
      },
      {
        $lookup: {
          from: "comments",
          localField: "_id",
          foreignField: "postId",
          pipeline: [
            {
              $lookup: {
                from: "users",
                localField: "user",
                foreignField: "_id",
                as: "user"
              }
            },
            {
              $unwind: "$user"
            }
          ],
          as: "comments"
        }
      }
    ])
    

    Mongo Playground