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

Comment interroger une clé dynamique - conception de schéma mongodb

Utilisation de MongoDB 3.4.4 et des versions plus récentes :

db.coll.aggregate([
    { "$replaceRoot": {
        "newRoot": {
            "$arrayToObject": {
                "$filter": {
                    "input": { "$objectToArray": "$$ROOT" },
                    "as": "el",
                    "cond": {
                        "$eq": [
                            "$$el.v.samekeyA",
                            "value1"
                        ]
                    }
                }
            }
        }   
    } }
])

Le pipeline ci-dessus donnera le résultat final

{
    "key1" : {
        "samekeyA" : "value1",
        "samekeyB" : "value2"
    }
}

Explications

Le pipeline peut être décomposé pour afficher les résultats de chaque opérateur individuel.

$objectToArray

$objectToArray vous permet de transformer le document racine avec des clés dynamiques (indiquées par la variable système $$ROOT ) dans un tableau contenant un élément pour chaque paire champ/valeur du document d'origine. Chaque élément du tableau de retour est un document qui contient deux champs k et v. Exécuter le pipeline avec juste l'opérateur dans un $project étape

db.coll.aggregate([
    { "$project": {
        "keys": { "$objectToArray": "$$ROOT" }
    } }
])

rendements

{
    "_id" : 1,
    "keys" : [ 
        {
            "k" : "_id",
            "v" : 1
        }, 
        {
            "k" : "key1",
            "v" : {
                "samekeyA" : "value1",
                "samekeyB" : "value2"
            }
        }, 
        {
            "k" : "key2",
            "v" : {
                "samekeyA" : "value3",
                "samekeyB" : "value4"
            }
        }, 
        {
            "k" : "key3",
            "v" : {
                "samekeyA" : "value5",
                "samekeyB" : "value6"
            }
        }
    ]
}

$filter

Le $filter agit comme un mécanisme de filtrage pour le tableau produit par $objectToArray , fonctionne en sélectionnant un sous-ensemble du tableau à renvoyer en fonction de la condition spécifiée qui devient votre requête.

Considérez le pipeline suivant qui renvoie un tableau de la paire clé/valeur qui correspond à la condition { "samekeyA": "value1" }

db.coll.aggregate([
    { "$project": {
        "keys": { 
            "$filter": {
                "input": { "$objectToArray": "$$ROOT" },
                "as": "el",
                "cond": {
                    "$eq": [
                        "$$el.v.samekeyA",
                        "value1"
                    ]
                }
            }  
        }
    } }
])

qui donne

{
    "_id" : 1,
    "keys" : [ 
        {
            "k" : "key1",
            "v" : {
                "samekeyA" : "value1",
                "samekeyB" : "value2"
            }
        }
    ]
}

$arrayToObject

Cela transformera le tableau filtré ci-dessus de

[ 
    {
        "k" : "key1",
        "v" : {
            "samekeyA" : "value1",
            "samekeyB" : "value2"
        }
    }
]

au document d'origine avec la clé dynamique

{
    "key1" : {
        "samekeyA" : "value1",
        "samekeyB" : "value2"
    }
}

donc en cours d'exécution du pipeline

db.coll.aggregate([
    { "$project": {
        "key": {
            "$arrayToObject": {
                "$filter": {
                    "input": { "$objectToArray": "$$ROOT" },
                    "as": "el",
                    "cond": {
                        "$eq": [
                            "$$el.v.samekeyA",
                            "value1"
                        ]
                    }
                }
            }
        }   
    } }
])

produira

{
    "_id" : 1,
    "key" : {
        "key1" : {
            "samekeyA" : "value1",
            "samekeyB" : "value2"
        }
    }
}

$replaceRoot

Cela promouvra le document de clé dynamique filtré au niveau supérieur et remplacera tous les autres champs. L'opération remplace tous les champs existants dans le document d'entrée, y compris le _id champ.

Cela transforme essentiellement le document ci-dessus

{
    "_id" : 1,
    "key" : {
        "key1" : {
            "samekeyA" : "value1",
            "samekeyB" : "value2"
        }
    }
}

au résultat final souhaité

{
    "key1" : {
        "samekeyA" : "value1",
        "samekeyB" : "value2"
    }
}