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

MongoDB $mergeObjects


No MongoDB, o $mergeObjects operador de pipeline de agregação combina vários documentos em um único documento.

Sintaxe


Os $mergeObjects O operador suporta duas sintaxes.

Sintaxe 1:
{ $mergeObjects: [ <document1>, <document2>, ... ] }

Sintaxe 2:
{ $mergeObjects: <document> }

A primeira sintaxe aceita vários argumentos e a segunda sintaxe aceita um argumento.

Exemplo de sintaxe 1 (vários argumentos)


A primeira sintaxe envolve fornecer $mergeObjects com mais de um argumento/documento. $mergeObjects em seguida, combina esses documentos em um.

Suponha que tenhamos uma coleção chamada users com o seguinte documento:
{
	"_id" : 1,
	"name" : {
		"f_name" : "Homer",
		"l_name" : "Simpson"
	},
	"contact" : {
		"email" : "[email protected]",
		"ph" : null
	}
}

Podemos usar $mergeObjects para mesclar o name e contact Campos:
db.users.aggregate(
  [
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$contact" ] }
        }
    }
  ]
).pretty()

Resultado:
{
	"_id" : 1,
	"user" : {
		"f_name" : "Homer",
		"l_name" : "Simpson",
		"email" : "[email protected]",
		"ph" : null
	}
}

Nesse caso, mesclamos os dois campos em um único campo chamado user . Se tivéssemos mais campos/documentos, poderíamos fundi-los também, se quiséssemos.

Nomes de campo duplicados


Se os documentos a serem mesclados contiverem nomes de campo duplicados, $mergeObjects substitui o campo à medida que mescla os documentos. Portanto, o campo no documento resultante contém o valor do último documento mesclado para esse campo.

Suponha que temos o seguinte documento:
{
	"_id" : 2,
	"name" : {
		"f_name" : "Peter",
		"l_name" : "Griffin"
	},
	"contact" : {
		"email" : "[email protected]",
		"f_name" : "Bart"
	}
}

Podemos ver que ambos os documentos contêm um campo chamado f_name .

Veja o que acontece quando mesclamos esses documentos:
db.users.aggregate(
  [
    { $match: { _id: 2 } },
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$contact" ] }
        }
    }
  ]
).pretty()

Resultado:
{
	"_id" : 2,
	"user" : {
		"f_name" : "Bart",
		"l_name" : "Griffin",
		"email" : "[email protected]"
	}
}

O f_name campo no documento resultante contém Bart , que é o valor do último documento que foi mesclado.

Valores nulos


Se estiver mesclando um documento com null , o documento resultante será devolvido sem alterações.

Mas se todos os documentos a serem mesclados forem null , um documento vazio é retornado.

Suponha que temos os seguintes documentos:
{
	"_id" : 3,
	"name" : {
		"f_name" : "Hubert",
		"l_name" : "Farnsworth"
	},
	"contact" : null
}
{ "_id" : 4, "name" : null, "contact" : null }

Veja o que acontece quando mesclamos o name e contact campos nesses dois documentos:
db.users.aggregate(
  [
    { $match: { _id: { $in: [ 3, 4 ] } } },
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$contact" ] }
        }
    }
  ]
)

Resultado:
{ "_id" : 3, "user" : { "f_name" : "Hubert", "l_name" : "Farnsworth" } }
{ "_id" : 4, "user" : {  } }

Exemplos de sintaxe 2 (argumento único)


Aqui estão dois exemplos que usam a sintaxe de argumento único.

$group Acumulador de Estágio


No primeiro exemplo, $mergeObjects é usado como um $group acumulador de palco.

Suponha que tenhamos uma coleção chamada products com os seguintes documentos:
{
	"_id" : 1,
	"product" : "Shirt",
	"inventory" : {
		"blue" : 10,
		"red" : 2
	}
}
{
	"_id" : 2,
	"product" : "Shirt",
	"inventory" : {
		"green" : 3,
		"black" : 1
	}
}
{
	"_id" : 3,
	"product" : "Shorts",
	"inventory" : {
		"blue" : 2,
		"red" : 8
	}
}
{
	"_id" : 4,
	"product" : "Shorts",
	"inventory" : {
		"green" : 5,
		"black" : 3
	}
}

Podemos agrupar esses documentos por seu product campo e, em seguida, use $mergeObjects para mesclar o inventory campo para cada grupo:
db.products.aggregate( [
   { $group: { 
     _id: "$product", 
     mergedProducts: { $mergeObjects: "$inventory" } 
     } 
    }
]).pretty()

Resultado:
{
	"_id" : "Shorts",
	"mergedProducts" : {
		"blue" : 2,
		"red" : 8,
		"green" : 5,
		"black" : 3
	}
}
{
	"_id" : "Shirt",
	"mergedProducts" : {
		"blue" : 10,
		"red" : 2,
		"green" : 3,
		"black" : 1
	}
}

Matrizes


Este exemplo se aplica a $mergeObjects para um único documento que contém um campo com uma matriz de documentos.

Suponha que tenhamos uma coleção chamada test com os seguintes documentos:
{
	"_id" : 1,
	"data" : [
		{
			"a" : 1,
			"b" : 2
		},
		{
			"c" : 3,
			"d" : 4
		}
	]
}

Podemos aplicar $mergeObjects para os data campo:
db.test.aggregate(
  [
    {
      $project:
        { 
          result: { $mergeObjects: "$data" }
        }
    }
  ]
)

Resultado:
{ "_id" : 1, "result" : { "a" : 1, "b" : 2, "c" : 3, "d" : 4 } }

Campos ausentes


$mergeObjects ignora quaisquer campos ausentes. Ou seja, se você fornecer um campo que não existe, ele o ignora. Se nenhum dos campos existir, ele retornará um documento vazio.

Exemplo:
db.users.aggregate(
  [
    {
      $project:
        { 
          user: { $mergeObjects: [ "$name", "$oops" ] }
        }
    }
  ]
).pretty()

Resultado:
{ "_id" : 1, "user" : { "f_name" : "Homer", "l_name" : "Simpson" } }
{ "_id" : 2, "user" : { "f_name" : "Peter", "l_name" : "Griffin" } }
{ "_id" : 3, "user" : { "f_name" : "Hubert", "l_name" : "Farnsworth" } }
{ "_id" : 4, "user" : { } }

No entanto, veja o que acontece quando nenhum dos campos existem:
db.users.aggregate(
  [
    {
      $project:
        { 
          user: { $mergeObjects: [ "$wrong", "$oops" ] }
        }
    }
  ]
).pretty()

Resultado:
{ "_id" : 1, "user" : { } }
{ "_id" : 2, "user" : { } }
{ "_id" : 3, "user" : { } }
{ "_id" : 4, "user" : { } }

O resultado é um documento vazio.

É o mesmo ao usar a sintaxe de argumento único.

Exemplo:
db.products.aggregate( [
   { $group: { 
     _id: "$product", 
     mergedProducts: { $mergeObjects: "$oops!" } 
     } 
    }
]).pretty()

Resultado:
{ "_id" : "Shorts", "mergedProducts" : { } }
{ "_id" : "Shirt", "mergedProducts" : { } }