通过嵌套数组查找猫鼬组
Posted
技术标签:
【中文标题】通过嵌套数组查找猫鼬组【英文标题】:Mongoose group by an lookup with nested arrays 【发布时间】:2021-10-17 22:50:13 【问题描述】:我有两个模式,第一个是 Quiz,另一个是 quizResults,我想在 quiz Schema 中查找时从 quizResult 中获取聚合数据。以下是我的测验模式:
vidId: type: Number, required: true,
status: type: Number, enum: [statusType.quizStatusEnums.LIVE, statusType.quizStatusEnums.DELETED], default: statusType.quizStatusEnums.LIVE,
questions: [
questionNum: type: Number ,
questionName: type: String ,
answers: [
answerId: type: String, default: uuid.v4() ,
answerName: type: String ,
isCorrect: type: Boolean ,
answerType: type: Number, enum: [statusType.quizTypeEnums.QUIZ, statusType.quizTypeEnums.SURVEY], default: statusType.quizTypeEnums.QUIZ,
hotspotId: type: Number ,
overlayId: type: Number,
panelId: type: String
]
],
第二个是QuizResults:需要对这个集合进行聚合查询。
created:
type: Date,
,
vidId:
type: Number,
required: true,
,
viewerId:
type: String,
required: true,
,
quizId:
type: Schema.Types.ObjectId,
ref: 'quiz'
,
questionId:
type: Schema.Types.ObjectId,
ref: 'quiz'
,
answerId:
type: String,
required: true
,
isCorrect:
type: Boolean,
default: false,
,
whenAnswered:
type: Date
,
我想要这样的最终聚合结果:
[
"questionNum": 2,
"questionName": "Which is the best selling record in history ?",
"correct": 10,
"incorrect": 20,
"totalAnswers": 30,
"answers": [
"answerId": "123abc",
"answerName": "Thriller Michel Jackson",
"numResponses": 10
,
"answerId": "234d",
"answerName": "A kind of Magic Queen",
"numResponses": 10
,
"answerId": "432e",
"answerName": "help The Beatles",
"numResponses": 10
]
,
"questionNum": 1,
"questionName": "What value has the number PI?",
"correct": 5,
"incorrect": 3,
"totalAnswers": 8,
"answers": [
"answerId": "111",
"answerName": "3.12",
"numResponses": 0
,
"answerId": "222",
"answerName": "3.14",
"numResponses": 5
,
"answerId": "333",
"answerName": "3.16",
"numResponses": 3
]
]
我尝试的是:
aggregate([
"$match": "vidId": 8225342, ,
"$group":
"_id": "$questionId",
"Correct":
"$sum":
"$cond": [
"$eq": ["$isCorrect", true] ,
1,
0
]
,
,
"Incorrect":
"$sum":
"$cond": [
"$eq": ["$isCorrect", false] ,
1,
0
]
,
,
"$lookup":
"from": "quiz",
"let": "id": "$_id" ,
"pipeline": [
"$match": "$expr": "$in": ["$$id", "$questions._id"] ,
"$unwind": "$questions" ,
"$match": "$expr": "$eq": ["$questions._id", "$$id"] ,
],
"as": "quizData"
,
$unwind: '$quizData' ,
"$project":
"questionName": "$quizData.questions.questionName",
"questionNum": "$quizData.questions.questionNum",
"Correct": "$Correct",
"Incorrect": "$Incorrect",
"answers": "$quizData.questions.answers" ,
])
我得到了类似的结果:
"_id": "611632305bd3910929b95552",
"questionName": "Which is the best selling record in history?",
"questionNum": 5,
"Correct": 3,
"Incorrect": 0,
"answers": [
"answerId": "078f441b-373f-40e9-89e1-04fca0a9fc5d",
"answerType": 0,
"_id": "611632305bd3910929b95553",
"answerName": "Thriller Michel Jackson",
"isCorrect": true,
"hotspotId": 470114,
"overlayId": 3,
"panelId": "12abc"
,
"answerId": "644b80fe-5778-46fa-b3a6-1eff5989cdee",
"answerType": 0,
"_id": "611632305bd3910929b95554",
"answerName": "A kind of Magic Queen",
"isCorrect": false,
"hotspotId": 470113,
"overlayId": 4,
"panelId": "12345abc"
,
"answerId": "5bde2682-66fe-4c79-a728-aea67f6842a8",
"answerType": 0,
"_id": "611632305bd3910929b95555",
"answerName": "help The Beatles",
"isCorrect": false,
"hotspotId": 470112,
"overlayId": 3,
"panelId": "12abc"
]
,
我怎样才能得到这样的 Answers 数组:
answers: [
answerId: "123abc",
answerName: "Thriller Michel Jackson",
numResponses: 10
,
answerId: "234d",
answerName: "A kind of Magic Queen",
numResponses: 10
,
answerId: "432e",
answerName: "help The Beatles",
numResponses: 10
]
【问题讨论】:
【参考方案1】:您可以尝试反过来处理它。使用$lookup
对quizResults
进行过滤和聚合,然后运行$map 和$filter 以获得每个答案的匹配统计信息:
db.quiz.aggregate([
$match: "vidId": 8225342
,
$lookup:
from: "quizResults",
pipeline: [
$match: "vidId": 8225342 ,
$group:
_id: "$answerId",
count: $sum: 1
],
as: "quizResults"
,
$project:
_id: 1,
questions:
$map:
input: "$questions",
as: "q",
in:
_id: "$$q._id",
questionName: "$$q.questionName",
questionNum: "$$q.questionNum",
answers:
$map:
input: "$$q.answers",
as: "a",
in:
$mergeObjects: [
"$$a",
$let:
vars:
fst:
$first:
$filter: input: "$quizResults", cond: $eq: [ "$$this._id", "$$a._id" ]
,
in: numResponses: "$$fst.count"
]
])
Mongo Playground
【讨论】:
我刚刚更新了我的问题,我期待答案数组包含每个答案的总和,每个答案给出了多少次。 @BilalMaher 您能否使用您的一些示例数据创建一个 Mongo Playground 以获得预期结果? 感谢您的评论我已经创建了一个 mongo 游乐场:mongoplayground.net/p/E4_0WYh3hpW @BilalMaher 谢谢你,这真的很有帮助,修改了我的答案 非常感谢您提出该查询,请您添加工作的 mongo 游乐场。我无法运行您在此处粘贴的查询。以上是关于通过嵌套数组查找猫鼬组的主要内容,如果未能解决你的问题,请参考以下文章
使用没有数组的嵌套文档为我的 JSON 定义有效的猫鼬模式?