Det finns ett speciellt knep för hur detta hanteras, men för det första om du har MongoDB 2.6 eller senare tillgängligt så kan du faktiskt göra vad du vill utan att använda $unwind
. Detta kan vara mycket praktiskt för prestanda om du bearbetar många dokument.
Nyckeloperatorerna här är $map
som behandlar arrayer på plats och $allElementsTrue
operatör som kommer att utvärdera dina "resultat"-fält. Användningen av "karta" här tillåter både testning av den inre "test"-arrayen för att se var "resultat"-fälten där alla uppfyller det sanna villkoret. I det yttre arrayfallet kan detta "resultat" placeras i dessa dokument som du behöver, och naturligtvis följer den fullständiga utvärderingen av dokumentet samma regler:
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"
}
}
}
}}
])
Sättet att göra detta i tidigare versioner kräver att du $min
operator som false
kommer att betraktas som ett lägre värde än true
och utvärderar till samma "allElements"-koncept:
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"
}
}
}}
])