MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

mongoDB :comment inverser $unwind

Il existe une astuce particulière pour gérer cela, mais tout d'abord, si vous disposez de MongoDB 2.6 ou d'une version supérieure, vous pouvez réellement faire ce que vous voulez sans utiliser $unwind . Cela peut être très pratique pour les performances si vous traitez beaucoup de documents.

Les opérateurs clés ici sont $map qui traite les tableaux en place et le $allElementsTrue opérateur qui évaluera vos champs "résultat". L'utilisation de "map" ici permet à la fois de tester le tableau interne "tests" pour voir où les champs "result" répondent tous à la vraie condition. Dans le cas du tableau externe, ce "résultat" peut être placé dans ces documents selon vos besoins, et bien sûr l'évaluation complète du document suit les mêmes règles :

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

Pour ce faire, dans les versions antérieures, vous devez $group revenir en deux étapes afin de "reconstruire" les tableaux tout en refaisant les tests sur ces champs "résultats". L'autre différence ici est également d'utiliser le $min opérateur comme false sera considéré comme une valeur inférieure à true et évalue le même concept "tous les éléments":

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