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 $unionWith toma un documento con los siguientes campos:
Campo | Descripción |
|---|---|
La colección o vista cuyos resultados del pipeline se desean incluir en el conjunto de resultados. | |
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 $unionWith forma parte del pipeline $lookup, el $unionWith coll no puede ser particionado. Por ejemplo, en la siguiente operación de agregación, la colección inventory_q1 no puede estar particionada:
db.suppliers.aggregate([ { $lookup: { from: "warehouses", let: { order_item: "$item", order_qty: "$ordered" }, pipeline: [ ... { $unionWith: { coll: "inventory_q1", pipeline: [ ... ] } }, ... ], as: "stockdata" } } ])
Intercalación
Si el db.collection.aggregate() incluye una intercalación, esa intercalación se utiliza para la operación, ignorando cualquier otra intercalación.
Si el db.collection.aggregate() no incluye una intercalación, el método db.collection.aggregate() utiliza la intercalación para la colección/vista de nivel superior en la que se ejecuta el db.collection.aggregate():
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 }