Поиск MongoDB, когда внешнее поле и локальное поле являются массивом объектов - PullRequest
1 голос
/ 30 мая 2020

У меня есть две коллекции «вопросы» и «ответы». вопросы документ выглядит следующим образом:

      [
        {
          _id: "8326ccbn73487290nc",
          questions: [
           {id: "12345", question: "Test", correct_answer: '0'},
           {id: "123456", question: "Test 2", correct_answer: '1'},
           {id: "1234567", question: "Test 3", correct_answer: '1'},
        ]
       },
       {
          _id: "8326ccbn734872ytruy90nclk",
          questions: [
           {id: "345", question: "Test", correct_answer: '0'},
           {id: "3456", question: "Test 2", correct_answer: '1'},
           {id: "34567", question: "Test 3", correct_answer: '1'},
        ]
       }
     ]

ответы документ выглядит так:

{
  id: '327rhrne7fr873',
  user_id: '43757fn574057fnf',
  question_id: '8326ccbn73487290nc',
  answers: [
    { id: '12345', student_answer: '1'},
    { id: '123456', student_answer: '0'},
  ]
}

поэтому я хочу вернуть что-то вроде этого :

[
    {
        _id: '8326ccbn73487290nc',
        questions: [
          {id: "12345", question: "Test", correct_answer: '0', student_answers: '1'},
          {id: "123456", question: "Test 2", correct_answer: '1', , student_answers: '0'},
          {id: "1234567", question: "Test 3", correct_answer: '1'},
        ]
    },
    {
          _id: "8326ccbn734872ytruy90nclk",
          questions: [
           {id: "345", question: "Test", correct_answer: '0'},
           {id: "3456", question: "Test 2", correct_answer: '1'},
           {id: "34567", question: "Test 3", correct_answer: '1'},
        ]
       }
]

Кто-нибудь может мне помочь, как я могу сделать что-то подобное.

Ответы [ 2 ]

1 голос
/ 31 мая 2020

Хотя в MongoDB можно получить желаемую структуру. Если вам не нужны дополнительные шаги агрегации, я бы посоветовал запрашивать только те данные, которые вам нужны, и выполнять отображение данных на уровне вашего приложения, потому что это намного проще, и мы не хотим слишком много работать с базой данных.

Однако вы можете использовать следующий подход для получения (близкого к) ожидаемого результата: я сохранил поле student_answer из коллекции answers и не переименовал его в student_answers, вы можете сделать дополнительные шаги при необходимости.

db.questions.aggregate([
  {
    $lookup: {
      from: "answers",
      let: {
        question_id: "$_id"
      },
      as: "answer",
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                {
                  $eq: [
                    "$question_id",
                    "$$question_id"
                  ]
                },
                {
                  $eq: [
                    "$user_id",
                    userId // insert user id variable here
                  ]
                }
              ]
            }
          }
        }
      ]
    }
  },
  {
    $unwind: {
      path: "$answer",
      preserveNullAndEmptyArrays: true
    }
  }, // up until this step, you already got all the data you need. You can stop here and do the extra steps in your application layer
  {
    $set: {
      questions: {
        $map: {
          input: "$questions",
          in: {
            $mergeObjects: [
              "$$this",
              {
                $arrayElemAt: [
                  {
                    $filter: {
                      input: "$answer.answers",
                      as: "answer",
                      cond: {
                        $eq: [
                          "$$this.id",
                          "$$answer.id"
                        ]
                      }
                    }
                  },
                  0
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: "answer" // cleanup by removing temporary field answer
  }
])

Пн go Детская площадка

0 голосов
/ 30 мая 2020

Вы можете использовать этот конвейер в предположении, что объект ответа соответствует одному объекту вопроса.

db.answers.aggregate([
    {
        $lookup: {
            from: "questions",
            let: {answerIds: {$map: {input: "$answers", as: "answer", in: "$$answer.id"}}},
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $gt: [
                                {
                                    $size: {
                                        $filter: {
                                            input: "$questions",
                                            as: "question",
                                            cond: {
                                                $setIsSubset: [["$$question.id"], "$$answerIds"]
                                            }
                                        }
                                    }
                                },
                                0
                            ]
                        }
                    }
                }
            ],
            as: "questions"
        }
    },
    {
        $unwind: "$questions"
    },
    {
        $project: {
            _id: "$questions._id",
            questions: {
                $map: {
                    input: "$questions.questions",
                    as: "question",
                    in: {
                        $mergeObjects: [
                            "$$question",
                            {
                                $ifNull: [
                                    {
                                        $arrayElemAt: [
                                            {
                                                $filter: {
                                                    input: "$answers",
                                                    as: "answer",
                                                    cond: {$eq: ["$$answer.id", "$$question.id"]}
                                                }
                                            }
                                            , 0
                                        ]
                                    },
                                    {}
                                ]
                            }
                        ]
                    }
                }
            }
        }
    }
])
...