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

So fragen Sie einen dynamischen Schlüssel ab – Mongodb-Schemadesign

Mit MongoDB 3.4.4 und neueren Versionen:

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

Die obige Pipeline liefert die endgültige Ausgabe

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

Erklärungen

Die Pipeline kann zerlegt werden, um die Ergebnisse jedes einzelnen Operators anzuzeigen.

$objectToArray

$objectToArray ermöglicht es Ihnen, das Stammdokument mit dynamischen Schlüsseln umzuwandeln (gekennzeichnet durch die Systemvariable $$ROOT ) in ein Array, das ein Element für jedes Feld/Wert-Paar im Originaldokument enthält. Jedes Element im Rückgabearray ist ein Dokument, das zwei Felder k und v enthält. Ausführen der Pipeline nur mit dem Operator in einem $project Stufe

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

Erträge

{
    "_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

Der $filter Der Operator fungiert als Filtermechanismus für das Array, das von $objectToArray -Operator funktioniert, indem er eine Teilmenge des Arrays auswählt, die basierend auf der angegebenen Bedingung zurückgegeben werden soll, die zu Ihrer Abfrage wird.

Betrachten Sie die folgende Pipeline, die ein Array des Schlüssel/Wert-Paares zurückgibt, das der Bedingung { "samekeyA":"value1" } entspricht

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

was ergibt

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

$arrayToObject

Dadurch wird das gefilterte Array oben von

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

zum Originaldokument mit dem dynamischen Schlüssel

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

also Ausführen der Pipeline

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

wird produzieren

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

$replaceRoot

Dadurch wird das gefilterte dynamische Schlüsseldokument auf die oberste Ebene befördert und ersetzt alle anderen Felder. Die Operation ersetzt alle vorhandenen Felder im Eingabedokument, einschließlich der _id aufstellen.

Im Wesentlichen transformiert dies das obige Dokument

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

zur gewünschten Endausgabe

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