MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como consultar uma chave dinâmica - design de esquema mongodb


Usando o MongoDB 3.4.4 e versões mais recentes:
db.coll.aggregate([
    { "$replaceRoot": {
        "newRoot": {
            "$arrayToObject": {
                "$filter": {
                    "input": { "$objectToArray": "$$ROOT" },
                    "as": "el",
                    "cond": {
                        "$eq": [
                            "$$el.v.samekeyA",
                            "value1"
                        ]
                    }
                }
            }
        }   
    } }
])

O pipeline acima produzirá a saída final
{
    "key1" : {
        "samekeyA" : "value1",
        "samekeyB" : "value2"
    }
}

Explicações


O pipeline pode ser decomposto para mostrar os resultados de cada operador individual.

$objectToArray

$objectToArray permite transformar o documento raiz com chaves dinâmicas (indicadas pela variável de sistema $$ROOT ) em uma matriz que contém um elemento para cada par de campo/valor no documento original. Cada elemento na matriz de retorno é um documento que contém dois campos k e v. Executando o pipeline apenas com o operador em um $project palco
db.coll.aggregate([
    { "$project": {
        "keys": { "$objectToArray": "$$ROOT" }
    } }
])

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

O $filter O operador atua como um mecanismo de filtragem para o array produzido pelo $objectToArray operador, funciona selecionando um subconjunto da matriz para retornar com base na condição especificada que se torna sua consulta.

Considere o seguinte pipeline que retorna uma matriz do par chave/valor que corresponde à condição { "samekeyA": "value1" }
db.coll.aggregate([
    { "$project": {
        "keys": { 
            "$filter": {
                "input": { "$objectToArray": "$$ROOT" },
                "as": "el",
                "cond": {
                    "$eq": [
                        "$$el.v.samekeyA",
                        "value1"
                    ]
                }
            }  
        }
    } }
])

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

$arrayToObject

Isso transformará a matriz filtrada acima de
[ 
    {
        "k" : "key1",
        "v" : {
            "samekeyA" : "value1",
            "samekeyB" : "value2"
        }
    }
]

para o documento original com a chave dinâmica
{
    "key1" : {
        "samekeyA" : "value1",
        "samekeyB" : "value2"
    }
}

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

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

$replaceRoot

Isso promoverá o documento de chave dinâmica filtrado ao nível superior e substituirá todos os outros campos. A operação substitui todos os campos existentes no documento de entrada, incluindo o _id campo.

Essencialmente, isso transforma o documento acima
{
    "_id" : 1,
    "key" : {
        "key1" : {
            "samekeyA" : "value1",
            "samekeyB" : "value2"
        }
    }
}

para a saída final desejada
{
    "key1" : {
        "samekeyA" : "value1",
        "samekeyB" : "value2"
    }
}