Ponieważ Twoim wymaganiem jest po prostu „zaprojektowanie” dokumentu tak, aby pole było zamaskowane, tak, struktura agregacji jest narzędziem do tego. Trochę zajmuje jednak ogarnięcie całego procesu podczas rozwijania tablic i rekonstrukcji.
Więc to, czego chciałeś, to:
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" }
}}
])
Ale tak naprawdę, jeśli masz MongoDB 2.6 lub nowszą wersję, nie musisz $rozwiń
i $group
wyniki z powrotem razem, aby pominąć to pole. Możesz teraz to zrobić za pomocą $project
i $map
operator, który działa z tablicami:
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
]
}
}
}
}}
])
Przepraszamy za wcięcie, które trochę przesuwa się poza stronę, ale nadal jest łatwiejszy do odczytania w porównaniu.
Pierwszy $map
przetwarza tablicę pytań na miejscu i przekazuje do wewnętrznego $mapa
który zwraca wewnętrzne dokumenty tablicy odpowiedzi bez pola „isCorrectAnswer”. Używa własnych zmiennych do reprezentowania elementów, a użycie $ifNull
tam jest tylko dlatego, że część "in" $mapa
operator oczekuje oceny warunku na każdym z tych elementów.
Ogólnie trochę szybciej, ponieważ nie musisz przechodzić przez $odpręż
i $group
operacje tylko w celu usunięcia pola. Tak więc naprawdę staje się to tylko „projekcją”, której można się spodziewać.