MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

mongoDB:come invertire $unwind

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"
            }
        }
    }}
])