Има конкретен трик как да се справите с това, но първо, ако имате MongoDB 2.6 или по-висока налична версия, тогава всъщност можете да правите каквото искате, без да използвате $unwind
. Това може да бъде много удобно за производителност, ако обработвате много документи.
Ключовите оператори тук са $map
който обработва масиви на място и $allElementsTrueкод>
оператор, който ще оцени вашите полета "резултат". Използването на "карта" тук позволява както тестването на вътрешния масив "тестове", за да се види къде всички полета "резултат" там отговарят на истинското условие. В случай на външен масив, този „резултат“ може да бъде поставен в тези документи, както желаете, и разбира се пълната оценка за документа следва същите правила:
db.test.aggregate([
{ "$project": {
"name": 1,
"result": {
"$allElementsTrue": {
"$map": {
"input": "$acts",
"as": "act",
"in": {
"$allElementsTrue": {
"$map": {
"input": "$$act.tests",
"as": "test",
"in": "$$test.result"
}
}
}
}
}
},
"acts": {
"$map": {
"input": "$acts",
"as": "act",
"in": {
"name": "$$act.name",
"result": {
"$allElementsTrue": {
"$map": {
"input": "$$act.tests",
"as": "test",
"in": "$$test.result"
}
}
},
"tests": "$$act.tests"
}
}
}
}}
])
Начинът да направите това в по-ранните версии изисква да $group
обратно в две стъпки, за да „възстановявате“ масивите, докато правите отново тестовете на тези полета за „резултат“. Другата разлика тук също е използването на $min
оператор като false
ще се счита за по-малка стойност от true
и се оценява на същата концепция „всички елементи“:
db.test.aggregate([
{ "$unwind": "$acts" },
{ "$unwind": "$acts.tests" },
{ "$group": {
"_id": {
"_id": "$_id",
"name": "$name",
"actName": "$acts.name"
},
"result": { "$min": "$acts.tests.result" },
"tests": {
"$push": {
"name": "$acts.tests.name",
"result": "$acts.tests.result"
}
}
}},
{ "$group": {
"_id": "$_id._id",
"name": { "$first": "$_id.name" },
"result": { "$min": "$result" },
"acts": {
"$push": {
"name": "$_id.actName",
"result": "$result",
"tests": "$tests"
}
}
}}
])