En MongoDB, el $unionWith
La etapa de canalización de agregación realiza una unión de dos colecciones e incluye duplicados.
Esto se comporta de manera similar a UNION ALL
de SQL , que también incluye duplicados. Por el contrario, usando solo UNION
(es decir, sin ALL
)en SQL elimina los duplicados.
En MongoDB, no tenemos la opción de especificar $unionWith ALL
o similar, por lo que debemos reducir los duplicados de otra manera.
En MongoDB, podemos eliminar duplicados usando el $group
escenario.
Ejemplo
Supongamos que insertamos los siguientes documentos en dos colecciones; uno llamado cats
y otro llamado 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 }
])
Y supongamos que ejecutamos la siguiente consulta para devolver todos los nombres de ambas colecciones:
db.cats.aggregate( [
{ $project: { name: 1, _id: 0 } },
{ $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} }
] )
Resultado:
{ "name" : "Fluffy" } { "name" : "Scratch" } { "name" : "Meow" } { "name" : "Wag" } { "name" : "Bark" } { "name" : "Fluffy" }
Podemos ver que el nombre Fluffy aparece dos veces. Esto se debe a que hay dos Fluffys en nuestras colecciones:uno en los cats
colección y uno en los dogs
colección.
Esto está bien si estamos felices de tener valores duplicados. Pero, ¿y si no lo hacemos? ¿Qué pasa si solo queremos una lista de nombres distintos de ambas colecciones?
Ahí es donde el $group
llega el escenario.
Podemos agregar el $group
etapa al name
campo, para que se vea así:
db.cats.aggregate( [
{ $project: { name: 1, _id: 0 } },
{ $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} },
{ $group: { _id: "$name" } }
] )
Resultado:
{ "_id" : "Meow" } { "_id" : "Bark" } { "_id" : "Scratch" } { "_id" : "Wag" } { "_id" : "Fluffy" }
Esta vez solo tenemos 5 documentos en lugar de 6, y solo hay un Fluffy.