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

Come eseguire query su una chiave dinamica - progettazione dello schema mongodb

Utilizzo di MongoDB 3.4.4 e versioni successive:

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

La pipeline di cui sopra produrrà l'output finale

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

Spiegazioni

La pipeline può essere scomposta per mostrare i risultati di ogni singolo operatore.

$objectToArray

$objectToArray consente di trasformare il documento radice con chiavi dinamiche (indicate dalla variabile di sistema $$ROOT ) in una matrice che contiene un elemento per ogni coppia campo/valore nel documento originale. Ogni elemento nell'array restituito è un documento che contiene due campi k e v. Esecuzione della pipeline solo con l'operatore in un $project fase

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

rendimenti

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

Il $filter operatore funge da meccanismo di filtraggio per l'array prodotto da $objectToArray operatore, funziona selezionando un sottoinsieme dell'array da restituire in base alla condizione specificata che diventa la tua query.

Considera la seguente pipeline che restituisce un array della coppia chiave/valore che corrisponde alla condizione { "samekeyA": "value1" }

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

che produce

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

$arrayToObject

Questo trasformerà l'array filtrato sopra da

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

al documento originale con la chiave dinamica

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

quindi eseguendo la pipeline

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

produrrà

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

$replaceRoot

Ciò promuoverà il documento chiave dinamica filtrato al livello superiore e sostituirà tutti gli altri campi. L'operazione sostituisce tutti i campi esistenti nel documento di input, incluso il _id campo.

In sostanza questo trasforma il documento sopra

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

all'output finale desiderato

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