sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo consultar una clave dinámica:diseño de esquema mongodb

Con MongoDB 3.4.4 y versiones más recientes:

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

La canalización anterior producirá el resultado final

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

Explicaciones

La canalización se puede descomponer para mostrar los resultados de cada operador individual.

$objectToArray

$objectToArray le permite transformar el documento raíz con claves dinámicas (indicado por la variable del sistema $$ROOT ) en una matriz que contiene un elemento para cada par de campo/valor en el documento original. Cada elemento de la matriz de retorno es un documento que contiene dos campos k y v. Ejecutar la canalización solo con el operador en un $project escenario

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

rendimientos

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

El $filter El operador actúa como un mecanismo de filtrado para la matriz producida por $objectToArray operador, funciona seleccionando un subconjunto de la matriz para devolver en función de la condición especificada que se convierte en su consulta.

Considere la siguiente canalización que devuelve una matriz del par clave/valor que coincide con la condición { "samekeyA": "value1" }

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

que produce

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

$arrayToObject

Esto transformará la matriz filtrada arriba de

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

al documento original con la clave dinámica

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

entonces ejecutando la canalización

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

producirá

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

$replaceRoot

Esto promoverá el documento clave dinámico filtrado al nivel superior y reemplazará todos los demás campos. La operación reemplaza todos los campos existentes en el documento de entrada, incluido el _id campo.

Esencialmente, esto transforma el documento anterior

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

al resultado final deseado

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