Docs Menu
Docs Home
/ /

$unionWith (etapa de agregación)

$unionWith

Combina dos agregaciones en un único conjunto de resultados. $unionWith produce el conjunto combinado de resultados (incluidos los duplicados) a la siguiente etapa.

El orden en el que se generan los documentos del conjunto de resultados combinado no está especificado.

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 procesa un documento con los siguientes campos:

Campo
Necesidad
Descripción

coll

Requerido si se omite pipeline. De lo contrario, opcional.

La colección o vista cuyos resultados del pipeline se desean incluir en el conjunto de resultados.

Si omite el campo coll, debe especificar un campo pipeline con una primera etapa de $documents.

Requerido si se omite coll. De lo contrario, opcional.

Una canalización de agregación para aplicar a los documentos de entrada.

  • Si especificas coll, el pipeline se aplica a los documentos en coll.

  • Si omites coll, la pipeline se aplica a los documentos en la etapa $documents de la pipeline. Para ver un ejemplo, consulta Crear una Unión con Documentos Especificados.

La canalización no puede incluir las etapas y. A partir de $out $merge la6.0 versión, la etapa pipeline puede contener Búsqueda de Atlas $search La etapa es la primera dentro del pipeline. Para obtener más información, consulte el soporte de búsqueda de Atlas.

La $unionWith operación correspondería a la siguiente instrucción SQL:

SELECT *
FROM Collection1
WHERE ...
UNION ALL
SELECT *
FROM Collection2
WHERE ...

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" }

Si la $unionWith etapa es parte del pipeline, la $unionWith coll no puede ser fragmentada. Por ejemplo, en la siguiente operación de agregación, la colección inventory_q1 no puede ser fragmentada:

db.suppliers.aggregate([
{
$lookup: {
from: "warehouses",
let: { order_item: "$item", order_qty: "$ordered" },
pipeline: [
...
{ $unionWith: { coll: "inventory_q1", pipeline: [ ... ] } },
...
],
as: "stockdata"
}
}
])

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á.

A partir de MongoDB,6.0 puede especificar la etapa de búsqueda $search de Atlas o en $searchMeta la $unionWith canalización para buscar colecciones en el clúster de Atlas. La $search etapa o debe ser la primera dentro de la $searchMeta $unionWith canalización.

[{
"$unionWith": {
"coll": <collection-name>,
"pipeline": [{
"$search": {
"<operator>": {
<operator-specification>
}
},
...
}]
}
}]
[{
"$unionWith": {
"coll": <collection-name>,
"pipeline": [{
"$searchMeta": {
"<collector>": {
<collector-specification>
}
},
...
}]
}
}]

Para ver un ejemplo de $unionWith con,$search consulte el tutorial de búsqueda en Atlas Ejecutar una consulta de búsqueda en Atlas $search usando $unionWith.

Advertencia

Las consultas que usan $unionWith con $search en la subcanalización podrían fallar durante una actualización de un conjunto de réplicas a un clúster fragmentado que ejecuta MongoDB v7.0 si la colección no está distribuida en varios fragmentos. Para mitigar esto, implemente más de un fragmento en el clúster y fragmente la colección de forma que varios fragmentos se distribuyan en varios fragmentos.

Restricciones
Descripción

Una canalización de agregación no puede utilizar $unionWith dentro de transacciones.

Colección particionada

Si la $unionWith etapa es parte de la pipeline, la $unionWith coll no se puede particionar.

La $unionWith pipeline no puede incluir la etapa $out.

La $unionWith pipeline no puede incluir la etapa $merge.

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.

  1. Crea una colección sales_2017 con 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 }
    ] )
  2. Crea una colección sales_2018 con 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 }
    ] )
  3. Crea una colección sales_2019 con 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 }
    ] )
  4. Crea una colección sales_2020 con 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 }
    ] )

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 $set etapa para actualizar el campo _id para que contenga el año.

  • Una secuencia de $unionWith etapas para combinar todos los documentos de las cuatro colecciones, cada una utilizando también la etapa $set en sus documentos.

  • Una $sort etapa para ordenar por el _id (el año), el store y item.

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 }

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 $unionWith etapas Recupera documentos de las colecciones especificadas en el pipeline:

  • La $group etapa agrupa por el campo item y utiliza $sum para calcular la cantidad total de ventas por item.

  • La $sort etapa ordena los documentos por total de 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 }

Puedes utilizar $unionWith para realizar una unión con los documentos que especifiques en el campo pipeline. Cuando especificas una etapa $documents en el campo pipeline, realizas una unión con documentos que no están almacenados en una colección separada.

Cree una colección cakeFlavors:

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

La siguiente operación $unionWith realiza una unión con los documentos especificados en el campo pipeline $documents:

db.cakeFlavors.aggregate( [
{
$unionWith: {
pipeline: [
{
$documents: [
{ _id: 4, flavor: "orange" },
{ _id: 5, flavor: "vanilla", price: 20 }
]
}
]
}
}
] )

Salida:

[
{ _id: 1, flavor: 'chocolate' },
{ _id: 2, flavor: 'strawberry' },
{ _id: 3, flavor: 'cherry' },
{ _id: 4, flavor: 'orange' },
{ _id: 5, flavor: 'vanilla', price: 20 }
]

Los ejemplos de C# en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulta Primeros pasos en la documentación del controlador de MongoDB .NET/C#.

La siguiente clase Movie modela los documentos en la colección sample_mflix.movies:

public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

Nota

ConventionPack para Pascal Case

Las clases de C# en esta página utilizan Pascal case para los nombres de sus propiedades, pero los nombres de los campos en la colección de MongoDB utilizan camel case. Para tener en cuenta esta diferencia, se puede usar el siguiente código para registrar un ConventionPack cuando la aplicación se inicie:

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

Para usar el controlador MongoDB.NET/C# para agregar una $unionWith etapa a una canalización de agregación, llame a UnionWith()método en un PipelineDefinition objeto.

El siguiente ejemplo crea una etapa de pipeline que combina los documentos entrantes de la colección sample_mflix.movies con los documentos Movie en la colección sample_mflix.Movies:

var firstMovieCollection = client.GetDatabase("sample_mflix").GetCollection<Movie>("movies");
var secondMovieCollection = client.GetDatabase("sample_mflix").GetCollection<Movie>("Movies");
var pipeline = new EmptyPipelineDefinition<Movie>()
.UnionWith(
withCollection: secondMovieCollection,
withPipeline: new EmptyPipelineDefinition<Movie>());
var allMovieDocuments = firstMovieCollection.Aggregate(pipeline);

Los ejemplos de Node.js en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Primeros pasos en la documentación del controlador de MongoDB Node.js.

Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $unionWith a una canalización de agregación, utilice el Operador $unionWith en un objeto de canalización.

El siguiente ejemplo crea una etapa de pipeline que combina los documentos entrantes de la colección sample_mflix.movies con los documentos movie de la colección sample_mflix.Movies. A continuación, el ejemplo ejecuta la canalización de agregación:

const db = client.db("sample_mflix");
const collection = db.collection("movies");
const pipeline = [{ $unionWith: { coll: "Movies" } }];
const cursor = collection.aggregate(pipeline);
return cursor;

Volver

$sortByCount

En esta página