Definición
$unionWithRealiza una unión de dos colecciones.
$unionWithcombina los resultados de la canalización de dos colecciones en un único conjunto de resultados. La etapa envía el conjunto de resultados combinado (incluidos los duplicados) a la siguiente etapa.El orden en el que se generan los documentos del conjunto de resultados combinado no está especificado.
Sintaxis
La etapa $unionWith tiene la siguiente sintaxis:
{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }
Para incluir todos los documentos de la colección especificada sin ningún procesamiento, puede utilizar la forma simplificada:
{ $unionWith: "<collection>" } // Include all documents from the specified collection
La etapa toma un documento con los siguientes $unionWith campos:
Campo | Descripción |
|---|---|
La colección o vista cuyos resultados del pipeline se desean incluir en el conjunto de resultados. | |
Opcional. Una canalización de agregación para aplicar a la colección especificada.
|
La $unionWith operación correspondería a la siguiente instrucción SQL:
SELECT * FROM Collection1 WHERE ... UNION ALL SELECT * FROM Collection2 WHERE ...
Considerations
Resultados duplicados
Los resultados combinados de la etapa anterior y la etapa$unionWith pueden incluir duplicados.
Por ejemplo, crea una colección suppliers y una colección warehouses:
db.suppliers.insertMany([ { _id: 1, supplier: "Aardvark and Sons", state: "Texas" }, { _id: 2, supplier: "Bears Run Amok.", state: "Colorado"}, { _id: 3, supplier: "Squid Mark Inc. ", state: "Rhode Island" }, ])
db.warehouses.insertMany([ { _id: 1, warehouse: "A", region: "West", state: "California" }, { _id: 2, warehouse: "B", region: "Central", state: "Colorado"}, { _id: 3, warehouse: "C", region: "East", state: "Florida" }, ])
La siguiente agregación combina los resultados de la proyección del campo state de las colecciones suppliers y warehouse.
db.suppliers.aggregate([ { $project: { state: 1, _id: 0 } }, { $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} } ])
El conjunto de resultados contiene duplicados:
{ "state" : "Texas" } { "state" : "Colorado" } { "state" : "Rhode Island" } { "state" : "California" } { "state" : "Colorado" } { "state" : "Florida" }
Para remover los duplicados, se puede incluir una etapa $group para agrupar por el campo state:
db.suppliers.aggregate([ { $project: { state: 1, _id: 0 } }, { $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} }, { $group: { _id: "$state" } } ])
El conjunto de resultados ya no contiene duplicados:
{ "_id" : "California" } { "_id" : "Texas" } { "_id" : "Florida" } { "_id" : "Colorado" } { "_id" : "Rhode Island" }
$unionWith una colección fragmentada
Si la etapa forma $unionWith parte de la canalización $lookup, la $unionWith colección no se puede fragmentar. Por ejemplo, en la siguiente operación de agregación, la inventory_q1 colección no se puede fragmentar:
db.suppliers.aggregate([ { $lookup: { from: "warehouses", let: { order_item: "$item", order_qty: "$ordered" }, pipeline: [ ... { $unionWith: { coll: "inventory_q1", pipeline: [ ... ] } }, ... ], as: "stockdata" } } ])
Intercalación
Si db.collection.aggregate() incluye una intercalación, esa intercalación se utiliza para la operación, ignorando cualquier otra intercalación.
Si no db.collection.aggregate() incluye una intercalación, el método utiliza la intercalación de la db.collection.aggregate() db.collection.aggregate() colección/vista de nivel superior en la que se ejecuta:
Si el $unionWith coll es una colección, se ignorará su intercalación.
Si el $unionWith coll es una vista, entonces su intercalación debe coincidir con la de la colección o vista de nivel superior. De lo contrario, la operación fallará.
Restricciones
Restricciones | Descripción |
|---|---|
Una canalización de agregación no puede utilizar | |
Colección particionada | Si la etapa es |
La $unionWith pipeline no puede incluir la etapa | |
La $unionWith pipeline no puede incluir la etapa |
Ejemplos
Crear informes de ventas a partir de la Unión de colecciones de datos anuales
Los siguientes ejemplos utilizan la etapa $unionWith para combinar datos y devolver resultados de múltiples colecciones. En estos ejemplos, cada colección contiene un año de datos de ventas.
Poblar datos de muestra
Crea una colección
sales_2017con los siguientes documentos:db.sales_2017.insertMany( [ { store: "General Store", item: "Chocolates", quantity: 150 }, { store: "ShopMart", item: "Chocolates", quantity: 50 }, { store: "General Store", item: "Cookies", quantity: 100 }, { store: "ShopMart", item: "Cookies", quantity: 120 }, { store: "General Store", item: "Pie", quantity: 10 }, { store: "ShopMart", item: "Pie", quantity: 5 } ] ) Crea una colección
sales_2018con los siguientes documentos:db.sales_2018.insertMany( [ { store: "General Store", item: "Cheese", quantity: 30 }, { store: "ShopMart", item: "Cheese", quantity: 50 }, { store: "General Store", item: "Chocolates", quantity: 125 }, { store: "ShopMart", item: "Chocolates", quantity: 150 }, { store: "General Store", item: "Cookies", quantity: 200 }, { store: "ShopMart", item: "Cookies", quantity: 100 }, { store: "ShopMart", item: "Nuts", quantity: 100 }, { store: "General Store", item: "Pie", quantity: 30 }, { store: "ShopMart", item: "Pie", quantity: 25 } ] ) Crea una colección
sales_2019con los siguientes documentos:db.sales_2019.insertMany( [ { store: "General Store", item: "Cheese", quantity: 50 }, { store: "ShopMart", item: "Cheese", quantity: 20 }, { store: "General Store", item: "Chocolates", quantity: 125 }, { store: "ShopMart", item: "Chocolates", quantity: 150 }, { store: "General Store", item: "Cookies", quantity: 200 }, { store: "ShopMart", item: "Cookies", quantity: 100 }, { store: "General Store", item: "Nuts", quantity: 80 }, { store: "ShopMart", item: "Nuts", quantity: 30 }, { store: "General Store", item: "Pie", quantity: 50 }, { store: "ShopMart", item: "Pie", quantity: 75 } ] ) Crea una colección
sales_2020con los siguientes documentos:db.sales_2020.insertMany( [ { store: "General Store", item: "Cheese", quantity: 100, }, { store: "ShopMart", item: "Cheese", quantity: 100}, { store: "General Store", item: "Chocolates", quantity: 200 }, { store: "ShopMart", item: "Chocolates", quantity: 300 }, { store: "General Store", item: "Cookies", quantity: 500 }, { store: "ShopMart", item: "Cookies", quantity: 400 }, { store: "General Store", item: "Nuts", quantity: 100 }, { store: "ShopMart", item: "Nuts", quantity: 200 }, { store: "General Store", item: "Pie", quantity: 100 }, { store: "ShopMart", item: "Pie", quantity: 100 } ] )
Informe 1: todas las ventas por año, almacenes y artículos
La siguiente agregación crea un informe anual de ventas que enumera todas las ventas por trimestre y por almacenes. El pipeline utiliza $unionWith para combinar documentos de las cuatro colecciones:
db.sales_2017.aggregate( [ { $set: { _id: "2017" } }, { $unionWith: { coll: "sales_2018", pipeline: [ { $set: { _id: "2018" } } ] } }, { $unionWith: { coll: "sales_2019", pipeline: [ { $set: { _id: "2019" } } ] } }, { $unionWith: { coll: "sales_2020", pipeline: [ { $set: { _id: "2020" } } ] } }, { $sort: { _id: 1, store: 1, item: 1 } } ] )
En concreto, la pipeline de agregación utiliza:
Una
$setetapa para actualizar el campo_idpara que contenga el año.Una secuencia de
$unionWithetapas para combinar todos los documentos de las cuatro colecciones, cada una utilizando también la etapa$seten sus documentos.Una
$sortetapa para ordenar por el_id(el año), elstoreyitem.
Salida del pipeline:
{ "_id" : "2017", "store" : "General Store", "item" : "Chocolates", "quantity" : 150 } { "_id" : "2017", "store" : "General Store", "item" : "Cookies", "quantity" : 100 } { "_id" : "2017", "store" : "General Store", "item" : "Pie", "quantity" : 10 } { "_id" : "2017", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 50 } { "_id" : "2017", "store" : "ShopMart", "item" : "Cookies", "quantity" : 120 } { "_id" : "2017", "store" : "ShopMart", "item" : "Pie", "quantity" : 5 } { "_id" : "2018", "store" : "General Store", "item" : "Cheese", "quantity" : 30 } { "_id" : "2018", "store" : "General Store", "item" : "Chocolates", "quantity" : 125 } { "_id" : "2018", "store" : "General Store", "item" : "Cookies", "quantity" : 200 } { "_id" : "2018", "store" : "General Store", "item" : "Pie", "quantity" : 30 } { "_id" : "2018", "store" : "ShopMart", "item" : "Cheese", "quantity" : 50 } { "_id" : "2018", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 150 } { "_id" : "2018", "store" : "ShopMart", "item" : "Cookies", "quantity" : 100 } { "_id" : "2018", "store" : "ShopMart", "item" : "Nuts", "quantity" : 100 } { "_id" : "2018", "store" : "ShopMart", "item" : "Pie", "quantity" : 25 } { "_id" : "2019", "store" : "General Store", "item" : "Cheese", "quantity" : 50 } { "_id" : "2019", "store" : "General Store", "item" : "Chocolates", "quantity" : 125 } { "_id" : "2019", "store" : "General Store", "item" : "Cookies", "quantity" : 200 } { "_id" : "2019", "store" : "General Store", "item" : "Nuts", "quantity" : 80 } { "_id" : "2019", "store" : "General Store", "item" : "Pie", "quantity" : 50 } { "_id" : "2019", "store" : "ShopMart", "item" : "Cheese", "quantity" : 20 } { "_id" : "2019", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 150 } { "_id" : "2019", "store" : "ShopMart", "item" : "Cookies", "quantity" : 100 } { "_id" : "2019", "store" : "ShopMart", "item" : "Nuts", "quantity" : 30 } { "_id" : "2019", "store" : "ShopMart", "item" : "Pie", "quantity" : 75 } { "_id" : "2020", "store" : "General Store", "item" : "Cheese", "quantity" : 100 } { "_id" : "2020", "store" : "General Store", "item" : "Chocolates", "quantity" : 200 } { "_id" : "2020", "store" : "General Store", "item" : "Cookies", "quantity" : 500 } { "_id" : "2020", "store" : "General Store", "item" : "Nuts", "quantity" : 100 } { "_id" : "2020", "store" : "General Store", "item" : "Pie", "quantity" : 100 } { "_id" : "2020", "store" : "ShopMart", "item" : "Cheese", "quantity" : 100 } { "_id" : "2020", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 300 } { "_id" : "2020", "store" : "ShopMart", "item" : "Cookies", "quantity" : 400 } { "_id" : "2020", "store" : "ShopMart", "item" : "Nuts", "quantity" : 200 } { "_id" : "2020", "store" : "ShopMart", "item" : "Pie", "quantity" : 100 }
Informe 2: ventas totales por artículos
La siguiente agregación crea un informe de ventas que enumera la cantidad de ventas por cada artículo. El pipeline utiliza $unionWith para combinar documentos de los cuatro años:
db.sales_2017.aggregate( [ { $unionWith: "sales_2018" }, { $unionWith: "sales_2019" }, { $unionWith: "sales_2020" }, { $group: { _id: "$item", total: { $sum: "$quantity" } } }, { $sort: { total: -1 } } ] )
La secuencia de
$unionWithetapas Recupera documentos de las colecciones especificadas en el pipeline:La
$groupetapa agrupa por el campoitemy utiliza$sumpara calcular la cantidad total de ventas poritem.La
$sortetapa ordena los documentos portotalde forma descendente.
Salida del pipeline:
{ "_id" : "Cookies", "total" : 1720 } { "_id" : "Chocolates", "total" : 1250 } { "_id" : "Nuts", "total" : 510 } { "_id" : "Pie", "total" : 395 } { "_id" : "Cheese", "total" : 350 }