No MongoDB, o
$unionWith
O estágio de pipeline de agregação realiza uma união de duas coleções e inclui duplicatas. Isso se comporta de maneira semelhante ao
UNION ALL
do SQL , que também inclui duplicatas. Por outro lado, usando apenas UNION
(ou seja, sem o ALL
) no SQL remove duplicatas. No MongoDB, não temos a opção de especificar
$unionWith ALL
ou similar, então precisamos reduzir duplicatas de outra maneira. No MongoDB, podemos remover duplicatas usando o
$group
etapa. Exemplo
Suponha que inserimos os seguintes documentos em duas coleções; um chamado
cats
e outro chamado dogs
:db.cats.insertMany([
{ _id: 1, name: "Fluffy", type: "Cat", weight: 5 },
{ _id: 2, name: "Scratch", type: "Cat", weight: 3 },
{ _id: 3, name: "Meow", type: "Cat", weight: 7 }
])
db.dogs.insertMany([
{ _id: 1, name: "Wag", type: "Dog", weight: 20 },
{ _id: 2, name: "Bark", type: "Dog", weight: 10 },
{ _id: 3, name: "Fluffy", type: "Dog", weight: 40 }
])
E suponha que executemos a seguinte consulta para retornar todos os nomes de ambas as coleções:
db.cats.aggregate( [
{ $project: { name: 1, _id: 0 } },
{ $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} }
] )
Resultado:
{ "name" :"Fofo" }{ "name" :"Scratch" }{ "name" :"Miau" }{ "name" :"Wag" }{ "name" :"Latido" }{ " name" :"Fofo" }
Podemos ver que o nome Fluffy aparece duas vezes. Isso ocorre porque existem dois Fluffys em nossas coleções – um nos
cats
coleção e um na coleção dogs
coleção. Isso é bom se estivermos felizes em ter valores duplicados. Mas e se não o fizermos? E se quisermos apenas uma lista de nomes distintos de ambas as coleções?
É aí que o
$group
palco entra. Podemos adicionar o
$group
palco para o name
campo, para que fique assim:db.cats.aggregate( [
{ $project: { name: 1, _id: 0 } },
{ $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} },
{ $group: { _id: "$name" } }
] )
Resultado:
{ "_id" :"Miau" }{ "_id" :"Bark" }{ "_id" :"Scratch" }{ "_id" :"Wag" }{ "_id" :"Fofo" }
Desta vez, recebemos apenas 5 documentos em vez de 6, e há apenas um Fluffy.