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"
}
}