Definición
$unionWithCambiado en la versión 8.0.
Combina dos agregaciones en un único conjunto de resultados.
$unionWithproduce 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.
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 collectionLa etapa $unionWith procesa un documento con los siguientes campos:
Campo | Necesidad | Descripción |
|---|---|---|
Requerido si se omite | La colección o vista cuyos resultados de canalización desea incluir en el conjunto de resultados. Si omite el campo | |
Requerido si se omite | Una canalización de agregación para aplicar a los documentos de entrada.
La pipeline no puede incluir las etapas |
La $unionWith operación correspondería a la siguiente instrucción SQL:
SELECT *FROM Collection1WHERE ...UNION ALLSELECT *FROM Collection2WHERE ...Considerations
Resultados duplicados
Los resultados combinados de la etapa anterior y la etapa$unionWith pueden incluir duplicados.
Por ejemplo, la siguiente agregación combina los resultados de proyección del campo title de dos consultas en la colección movies. El conjunto de resultados contiene duplicados:
db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } } ] } }] )[ { title: 'Centennial' }, { title: 'Baseball' }, { title: 'Centennial' }, { title: 'Baseball' }]Para eliminar los duplicados, puede incluir una etapa $group para agrupar por el campo title. El conjunto de resultados ya no contiene duplicados:
db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } } ] } }, { $group: { _id: "$title" } }, { $sort: { _id: 1 } }] )[ { _id: 'Baseball' }, { _id: 'Centennial' }]Intercalación
Si el db.collection.aggregate() incluye un documento collation, la operación utiliza esa intercalación y omite cualquier otra intercalación.
Si el db.collection.aggregate() no incluye un documento collation, 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á.
Soporte de Atlas Search
A partir de MongoDB 6.0, puedes especificar la etapa de Atlas Search $search o $searchMeta en la $unionWith pipeline para buscar colecciones en el clúster de Atlas. La $search o la $searchMeta etapa debe ser la primera etapa dentro del pipeline $unionWith.
[{ "$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, consulta el tutorial de Atlas Search Ejecutar una Atlas Search $search query utilizando $unionWith.
Namespaces en subcanalizaciones
A partir de MongoDB 8.0, namespaces en subpipelines dentro de $lookup y $unionWith se validan para asegurar el uso correcto de los campos from y coll:
Para
$lookup, omite el campofromsi utilizas una subpipeline con una etapa que no requiera una colección especificada. Por ejemplo, una etapa$documents.De manera similar, para
$unionWith, omite el campocoll.
Comportamiento sin cambio:
Para un
$lookupque comienza con una etapa para una colección, por ejemplo, una sub-etapa$matcho$collStats, debes incluir el campofromy especificar la colección.De manera similar, para
$unionWith, incluye el campocolly especifica la colección.
Restricciones
Restricciones | Descripción |
|---|---|
Una pipeline de agregación no puede utilizar | |
La $unionWith pipeline no puede incluir la | |
La $unionWith pipeline no puede incluir la |
Ejemplos
Los ejemplos de esta página utilizan datos del conjunto de datos sample_mflix. Para obtener más información sobre cómo cargar este conjunto de datos en la implementación autogestionada de MongoDB, consultar Cargar el conjunto de datos de muestra. Si realizó alguna modificación en las bases de datos de muestra, es posible que deba descartar y volver a crear las bases de datos para ejecutar los ejemplos de esta página.
Cree informes de películas a partir de la Unión de Datos de Películas.
Los siguientes ejemplos utilizan la etapa $unionWith para combinar datos y devolver resultados de la colección movies.
Informe 1: Todas las películas por categoría y año
La siguiente agregación crea un informe de películas que las lista por categoría. El proceso utiliza $unionWith para combinar documentos de la colección movies:
db.movies.aggregate( [ { $match: { year: { $lt: 1910 } } }, { $set: { category: "Early Cinema" } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } }, { $set: { category: "Long Runtime" } } ] } }, { $project: { title: 1, year: 1, category: 1, _id: 0 } }, { $sort: { category: 1, year: 1, title: 1 } }] )[ { title: 'The Kiss', year: 1896, category: 'Early Cinema' }, { title: 'The Kiss', year: 1896, category: 'Early Cinema' }, { title: 'The Great Train Robbery', year: 1903, category: 'Early Cinema' }, { title: 'A Corner in Wheat', year: 1909, category: 'Early Cinema' }, { title: 'Centennial', year: 1978, category: 'Long Runtime' }, { title: 'Baseball', year: 1994, category: 'Long Runtime' }]En concreto, la pipeline de agregación utiliza:
Una etapa
$matchpara seleccionar películas estrenadas antes de1910.Una etapa
$setpara agregar un campocategorycon el valorEarly Cinema.Una etapa
$unionWithpara combinar documentos de la colecciónmovies, filtrados a películas con unruntimemayor que1000y etiquetados con la categoríaLong Runtime.Una etapa
$projectpara devolver solo los campostitle,yearycategory.Una etapa
$sortpara clasificar porcategory,yearytitle.
Informe 2: Tiempo de ejecución agregado por género
La siguiente agregación crea un informe de películas que enumera el tiempo total de ejecución por género. El proceso utiliza $unionWith para combinar documentos de la colección movies:
db.movies.aggregate( [ { $match: { year: { $lt: 1910 } } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } } ] } }, { $group: { _id: "$genres", totalRuntime: { $sum: "$runtime" } } }, { $sort: { totalRuntime: -1 } }] )[ { _id: [ 'Action', 'Adventure', 'Drama' ], totalRuntime: 1256 }, { _id: [ 'Documentary', 'History', 'Sport' ], totalRuntime: 1140 }, { _id: [ 'Short', 'Drama' ], totalRuntime: 14 }, { _id: [ 'Short', 'Western' ], totalRuntime: 11 }, { _id: [ 'Short', 'Romance' ], totalRuntime: 2 }]Las etapas
$matchy$unionWithrecuperan documentos de la colecciónmoviesen la canalización.La etapa
$groupagrupa por el campogenresy utiliza$sumpara calcular elruntimetotal por valorgenres.La
$sortetapa ordena los documentos portotalRuntimede forma descendente.
Crea una unión con documentos específicos
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.
La siguiente operación $unionWith realiza una unión con los documentos especificados en el campo pipeline $documents:
db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, year: 1, _id: 0 } }, { $unionWith: { pipeline: [ { $documents: [ { title: "Movie A", year: 2000 }, { title: "Movie B", year: 2001 } ] } ] } }] )[ { title: 'Centennial', year: 1978 }, { title: 'Baseball', year: 1994 }, { title: 'Movie A', year: 2000 }, { title: 'Movie B', year: 2001 }]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:
[BsonIgnoreExtraElements]public class Movie{ [BsonId] public ObjectId Id { get; set; } [BsonElement("title")] public string Title { get; set; } = null!; [BsonElement("year")] public int? Year { get; set; } [BsonElement("runtime")] public int? Runtime { get; set; } [BsonElement("rated")] public string? Rated { get; set; } [BsonElement("metacritic")] public int Metacritic { get; set; } [BsonElement("plot")] public string? Plot { get; set; } [BsonElement("type")] public string? Type { get; set; } [BsonElement("cast")] public string[]? Cast { get; set; } [BsonElement("directors")] public string[]? Directors { get; set; } [BsonElement("writers")] public string[]? Writers { get; set; } [BsonElement("imdb")] public ImdbData? Imdb { get; set; }}Para utilizar el controlador de MongoDB .NET/C# para añadir una etapa $unionWith a una canalización de agregación, llame al método UnionWith() en un objeto PipelineDefinition.
El siguiente ejemplo crea una etapa de la pipeline que combina películas con una puntuación Metacritic de 100 de la colección sample_mflix.movies con películas que cumplen los mismos criterios:
var pipeline = new EmptyPipelineDefinition<Movie>() .Match(Builders<Movie>.Filter.Eq(m => m.Metacritic, 100)) .UnionWith( withCollection: _movies, withPipeline: new EmptyPipelineDefinition<Movie>() .Match(Builders<Movie>.Filter.Eq(m => m.Metacritic, 100)));{ "metacritic" : 100, "title" : "Best Kept Secret" }{ "metacritic" : 100, "title" : "Best Kept Secret" }{ "metacritic" : 100, "title" : "Boyhood" }{ "metacritic" : 100, "title" : "Boyhood" }{ "metacritic" : 100, "title" : "Fanny and Alexander" }{ "metacritic" : 100, "title" : "Fanny and Alexander" }{ "metacritic" : 100, "title" : "Lawrence of Arabia" }{ "metacritic" : 100, "title" : "Lawrence of Arabia" }{ "metacritic" : 100, "title" : "The Conformist" }{ "metacritic" : 100, "title" : "The Conformist" }{ "metacritic" : 100, "title" : "The Godfather" }{ "metacritic" : 100, "title" : "The Godfather" }{ "metacritic" : 100, "title" : "The Leopard" }{ "metacritic" : 100, "title" : "The Leopard" }{ "metacritic" : 100, "title" : "The Wizard of Oz" }{ "metacritic" : 100, "title" : "The Wizard of Oz" }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;