Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当外部字段和本地字段是对象数组时的MongoDB查找_Mongodb_Mongodb Query_Aggregation Framework_Aggregate - Fatal编程技术网

当外部字段和本地字段是对象数组时的MongoDB查找

当外部字段和本地字段是对象数组时的MongoDB查找,mongodb,mongodb-query,aggregation-framework,aggregate,Mongodb,Mongodb Query,Aggregation Framework,Aggregate,我有两套“问题”和“答案”。 问题文档如下: [ { _id: "8326ccbn73487290nc", questions: [ {id: "12345", question: "Test", correct_answer: '0'}, {id: "123456", question: "Test 2", correct_answer: '1'}, {id:

我有两套“问题”和“答案”。 问题文档如下:

      [
        {
          _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'},
        ]
       }
]
所以我想返回如下内容:

{
  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'},
        ]
       }
]

有人能帮我怎么做吗。

你可以在假设答案对象与单个问题对象匹配的情况下使用这个管道

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
                                        ]
                                    },
                                    {}
                                ]
                            }
                        ]
                    }
                }
            }
        }
    }
])

尽管可以在MongoDB中获得所需的结构。如果您不需要额外的聚合步骤,我建议只查询您需要的数据,并在应用程序层中进行数据映射,因为这样更容易,而且我们不想在数据库上做太多工作

但是,您可以使用以下方法获得(接近)您的预期输出,我保留了
答案
集合中的
学生答案
字段,并且没有将其重命名为
学生答案
,如果需要,您可以执行额外的步骤

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


整个集合中是否只有一个问题对象?一个问题是否可以位于具有不同id的多个问题对象中?整个集合中可能有多个问题。不,一个问题不能在多个不同id的问题上。再问一个问题,一个答案对象可以匹配两个问题对象吗?不,它不能匹配两个问题对象。我只想要一个答案,因为我用用户id发出get请求。对不起,汤姆,可能我不清楚。我想在我的回答中使用与问题文档相同的JSON,但只是添加了“student_answer”(如果有值)。当我打电话询问我所有的问题时,我希望得到这样的回答。是的,回答回来了,不是这样吗?你试过了吗?是的。我试试看。我只得到对答案集有价值的问题(在我的情况下,我想要所有的问题,如果它们对答案集没有价值),我的回答没有正确的答案。我认为查询将是对问题集的,而不是对答案的。难道一个问题没有多个答案吗?多个学生。。?根据答案做这件事更有意义,但从理论上讲,你可以颠倒
$lookup
,其余的都差不多。你做得很好。多谢各位。当我在代码中实现它时,我必须解决为什么会得到“无法识别的管道阶段名称:“$set”。我的结构看起来很好,就像您的一样。您可能使用的是较旧的MongoDB版本,请尝试使用
$addFields
而不是
$set
{$project:{answer:false}}}
而不是
$unset:“answer”
非常感谢。这就是我想要的