MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

mongoDB:wie man $unwind umkehrt

Es gibt einen besonderen Trick, wie dies gehandhabt wird, aber erstens, wenn Sie MongoDB 2.6 oder höher zur Verfügung haben, können Sie tatsächlich tun, was Sie wollen, ohne $unwind . Dies kann für die Leistung sehr praktisch sein, wenn Sie viele Dokumente verarbeiten.

Die wichtigsten Operatoren hier sind $map der Arrays an Ort und Stelle verarbeitet, und den $allElementsTrue Operator, der Ihre "Ergebnis"-Felder auswertet. Die Verwendung von „map“ hier ermöglicht sowohl das Testen des inneren „tests“-Arrays, um zu sehen, wo die „result“-Felder darin alle die wahre Bedingung erfüllen. Im Fall des äußeren Arrays kann dieses "Ergebnis" nach Bedarf in diese Dokumente eingefügt werden, und natürlich folgt die vollständige Auswertung für das Dokument denselben Regeln:

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

Um dies in früheren Versionen zu tun, müssen Sie $group in zwei Schritten zurück, um die Arrays "neu aufzubauen", während die Tests für diese "Ergebnis"-Felder erneut durchgeführt werden. Der andere Unterschied hier ist auch die Verwendung des $min Operator als false wird als kleinerer Wert als true betrachtet und wertet nach demselben "allElements"-Konzept aus:

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