Eftersom ditt krav är att bara "projicera" dokumentet så att fältet är maskerat, ja aggregeringsramverket är ett verktyg för att göra detta. Det tar dock lite att komma runt processen när du lindar upp arrayer och rekonstruerar.
Så det du ville ha var detta:
db.collection.aggregate([
{ "$unwind": "$questions" },
{ "$unwind": "$questions.answers" },
{ "$group": {
"_id": {
"_id": "$_id",
"name": "$name",
"description": "$description",
"qid": "$questions._id",
"question": "$questions.question"
},
"answers": {
"$push": {
"_id": "$questions.answers._id",
"answer": "$questions.answers.answer"
}
}
}},
{ "$project": {
"questions": {
"_id": "$_id.qid",
"question": "$_id.question",
"answers": "$answers"
}
}},
{ "$sort": { "_id": 1, "questions._id": 1 } },
{ "$group": {
"_id": "$_id._id",
"name": { "$first": "$_id.name" },
"description": { "$first": "$_id.description" },
"questions": { "$push": "$questions" }
}}
])
Men egentligen, om du har en MongoDB 2.6 eller senare version behöver du inte $unwind
och $group
resultaten sammanförs igen för att utelämna det fältet. Du kan nu bara göra detta med $project
och $map
operator som fungerar med arrayer:
db.collection.aggregate([
{ "$project": {
"name": 1,
"description": 1,
"questions": {
"$map": {
"input": "$questions",
"as": "q",
"in": {
"$ifNull": [
{
"_id": "$$q._id",
"question": "$$q.question",
"answers": {
"$map": {
"input": "$$q.answers",
"as": "el",
"in": {
"$ifNull": [
{ "_id": "$$el._id", "answer": "$$el.answer" },
false
]
}
}
}
},
false
]
}
}
}
}}
])
Ursäkta för indraget som rullar av sidan lite där, men det är ändå lättare att läsa i jämförelse.
Den första $map
behandlar frågeuppsättningen på plats och matar till en inre $map
som returnerar de inre svarsarraydokumenten utan fältet "isCorrectAnswer". Den använder sina egna variabler för att representera elementen, och användningen av $ifNull
där är bara för att "in"-delen av $map
operatören förväntar sig att utvärdera ett villkor för vart och ett av dessa element.
Sammantaget lite snabbare, eftersom du inte behöver gå igenom $unwind
och $group
operationer bara för att ta bort fältet. Så det blir egentligen bara den "projektion" som du kan förvänta dig.