当外部字段和本地字段是对象数组时的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”
非常感谢。这就是我想要的