C'è un trucco particolare su come questo viene gestito, ma in primo luogo se hai MongoDB 2.6 o versioni successive, puoi effettivamente fare ciò che vuoi senza usare $unwind
. Questo può essere molto utile per le prestazioni se stai elaborando molti documenti.
Gli operatori chiave qui sono $map
che elabora gli array in atto e $allElementsTrue
operatore che valuterà i tuoi campi "risultato". L'uso di "mappa" qui consente sia il test dell'array "tests" interno per vedere dove i campi "risultato" presenti soddisfano tutti la condizione vera. Nel caso dell'array esterno, questo "risultato" può essere inserito in quei documenti come richiesto e, naturalmente, la valutazione completa del documento segue le stesse regole:
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"
}
}
}
}}
])
Il modo per farlo nelle versioni precedenti richiede di $group
indietro in due passaggi per "ricostruire" gli array mentre si eseguono nuovamente i test su quei campi "risultato". L'altra differenza qui è anche l'utilizzo di $min
operatore come false
sarà considerato un valore inferiore a true
e restituisce lo stesso concetto "allElements":
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"
}
}
}}
])