Search code examples
mongodbmongooseaggregation-frameworkmongoose-populate

Retrieve Array Data Using Populate from One Model to Another


Here the two models of my MongoDB database.

QuestionsInfo


{
    "_id": ObjectId("60e5f5fce2446faa95e6eca7"),
    "courseName": "ML",
    "user": ObjectId("6087dc4c2ba7a828363c9fca"),
    "questions": [
        {
            "questionInput": {
                "question": "This is the first Question. `(a+b)^2` ",
            },
            "id": "aLC/QNz/AOLO9Fyj7oJT",
            "createdAt": "2021-07-07T18:41:18.971Z"
        },
        {
            "questionInput": {
                "question": "This is the first Question. `(a+b)^2` ",
            },
            "id": "aLC/QNz/AOLO9Fyj7oJJ",
            "createdAt": "2021-07-07T18:41:19.971Z"
        },
        {
            "questionInput": {
                "question": "This is the third Question.ΒΓ",
            },
            "id": "qPgd261wVGizOuR1b9RT",
            "createdAt": "2021-07-07T18:46:25.203Z"
        }
    ]
}

ExamInfo

questionsInfo is the id of the QuestionsInfo model. This is created by MongoDB reference.

{
    "_id": ObjectId("60e5f88159292f575c0ca17f"),
    "questionsId": [
        "aLC/QNz/AOLO9Fyj7oJT",
        "aLC/QNz/AOLO9Fyj7oJJ"
    ],
    "user": ObjectId("6087dc4c2ba7a828363c9fca"),
    "questionsInfo": ObjectId("60e5f5fce2446faa95e6eca7"),
}

I want to find questions from QuestionsInfo that matches the questionsId list using populate into the ExamInfo model.

How can I do this? Thanks in advance.


Solution

  • Here's how you can achieve this.

    {
        $lookup: {
          from: "questionsInfo",
          let: {
            qId: "$questionsInfo",
            internalQIds: "$questionsId"
          },
          as: "questionsInfo",
          pipeline: [
            // first match question info document
            {
              $match: {
                $expr: {
                  $eq: [
                    "$_id",
                    "$$qId"
                  ]
                }
              }
            },
            // unwind all nested questions
            {
              $unwind: "$questions"
            },
            // match only required questions
            {
              $match: {
                $expr: {
                  $in: [
                    "$questions.id",
                    "$$internalQIds"
                  ]
                }
              }
            },
            // regroup
            {$group: {
              _id: "$_id",
              courseName: {
                $first: "$courseName"
              },
              user: {
                $first: "user"
              },
              questions: {
                $push: "$questions"
              }
            }
          },
          
        ]
      }
    }
    

    Now since lookup returns array you can use something like this to take out question info from array.

    {
      "$addFields": {
        "questionsInfo": {
          "$arrayElemAt": [
            "$questionsInfo",
            0
          ]
        }
      }
    }
    

    https://mongoplayground.net/p/lYQAUFyEUMr