Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / /

$unionWith (agregação)

Nesta página

  • Definição
  • Sintaxe
  • Considerações
  • Resultados duplicados
  • $unionWith uma collection fragmentada
  • Agrupamentos
  • Suporte do Atlas Search
  • Restrições
  • Exemplos
  • Criar relatórios de vendas a partir da união de collections de dados anuais
  • Relatório 1: todas as vendas por ano e lojas e itens
  • Relatório 2: vendas agregadas por itens
  • Crie uma união com documentos especificados
  • Namespaces em Subpipelines
$unionWith

Alterado na versão 8.0.

Combina duas agregações em um único conjunto de resultados. $unionWith produz o conjunto de resultados combinado (incluindo duplicidades) para o próximo estágio.

A ordem na qual os documentos combinados do conjunto de resultados são produzidos não é especificada.

O estágio $unionWith tem a seguinte sintaxe:

{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }

Para incluir todos os documentos da collection especificada sem processamento, você pode usar o formato simplificado:

{ $unionWith: "<collection>" } // Include all documents from the specified collection

O estágio $unionWith recebe um documento com os seguintes campos:

Campo
necessidade
Descrição

coll

Obrigatório se pipeline for omitido. Caso contrário, opcional.

A collection or visualização cujos resultados de pipeline que você deseja incluir no conjunto de resultados.

Se você omitir o campo coll , deverá especificar um campo pipeline com um primeiro estágio de $documents.

Obrigatório se coll for omitido. Caso contrário, opcional.

Um pipeline de agregação para aplicar aos documentos de entrada.

  • Se você especificar coll, o pipeline se aplicará aos documentos em coll.

  • Se você omitir coll, o pipeline se aplicará aos documentos no $documents estágio do pipeline. Para obter um exemplo, consulte Criar uma união com documentos especificados.

O pipeline não pode incluir os estágios e. A partir de $out $merge v6.0, o pipeline pode conter o estágio Atlas Search $search como o primeiro estágio dentro do pipeline. Para saber mais, consulte Suporte do Atlas Search .

A operação $unionWith corresponderia à seguinte declaração SQL:

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

Os resultados combinados do estágio anterior e do estágio $unionWith podem incluir duplicatas.

Por exemplo, crie uma collection suppliers e uma collection 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" },
])

A seguinte aggregation combina os resultados da projeção de campo state das collections suppliers e warehouse.

db.suppliers.aggregate([
{ $project: { state: 1, _id: 0 } },
{ $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} }
])

O conjunto de resultados contém duplicatas:

{ "state" : "Texas" }
{ "state" : "Colorado" }
{ "state" : "Rhode Island" }
{ "state" : "California" }
{ "state" : "Colorado" }
{ "state" : "Florida" }

Para remover as duplicatas, você pode incluir um estágio $group para agrupar pelo campo state:

db.suppliers.aggregate([
{ $project: { state: 1, _id: 0 } },
{ $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} },
{ $group: { _id: "$state" } }
])

O conjunto de resultados não contém mais duplicatas:

{ "_id" : "California" }
{ "_id" : "Texas" }
{ "_id" : "Florida" }
{ "_id" : "Colorado" }
{ "_id" : "Rhode Island" }

Se o estágio $unionWith fizer parte do pipeline $lookup, a coleção $unionWith não poderá ser fragmentada. Por exemplo, na seguinte operação de agregação, a coleção inventory_q1 não pode ser fragmentada:

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

Se db.collection.aggregate() incluir um documento collation , esse agrupamento será usado para a operação, ignorando quaisquer outros agrupamentos.

Se db.collection.aggregate() não incluir um documento collation , o método db.collection.aggregate() usará o agrupamento para o agrupamento/visualização de nível superior no qual db.collection.aggregate() é executado:

  • Se $unionWith coll for uma coleção, seu agrupamento será ignorado.

  • Se $unionWith coll for uma visualização, seu agrupamento deverá corresponder ao da coleção/visualização de nível superior. Caso contrário, a operação apresentará erro.

A partir do MongoDB 6.0, você pode especificar o $search do Atlas Search ou o estágio do $searchMeta no pipeline de $unionWith para pesquisar coleções no cluster do Atlas. O estágio $search ou $searchMeta deve ser o primeiro dentro do pipeline $unionWith.

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

Para ver um exemplo de $unionWith com $search, consulte o tutorial Como executar uma query $search do Atlas Search usando $unionWith.

Restrições
Descrição

Um pipeline de agregação não pode usar $unionWith dentro de transações.

Collection fragmentada

Se o estágio $unionWith fizer parte do pipeline $lookup, collection $unionWith não poderá ser fragmentado.

O pipeline $unionWith não pode incluir o $out estágio.

O pipeline $unionWith não pode incluir o $merge estágio.

Os exemplos a seguir usam o estágio $unionWith para combinar dados e retornar resultados de várias coleções. Nesses exemplos, cada coleção contém um ano de dados de vendas.

  1. Criar uma coleção sales_2017 com os seguintes 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. Criar uma coleção sales_2018 com os seguintes 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. Criar uma coleção sales_2019 com os seguintes 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. Criar uma coleção sales_2020 com os seguintes 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 }
    ] )

A seguinte agregação cria um relatório de vendas anual que lista todas as vendas por trimestre e lojas. O pipeline usa $unionWith para combinar documentos de todas as quatro coleções:

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 } }
] )

Especificamente, o aggregation pipeline usa:

  • Um estágio $set para atualizar o campo _id para conter o ano.

  • Uma sequência de estágios $unionWith para combinar todos os documentos das quatro coleções, cada qual também usando o estágio $set em seus documentos.

  • Um estágio $sort para classificar pelo _id (o ano), store e item.

Resultado do 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 }

A seguinte agregação cria um relatório de vendas que lista a quantidade de vendas por item. O pipeline usa $unionWith para combinar documentos de todos os quatro anos:

db.sales_2017.aggregate( [
{ $unionWith: "sales_2018" },
{ $unionWith: "sales_2019" },
{ $unionWith: "sales_2020" },
{ $group: { _id: "$item", total: { $sum: "$quantity" } } },
{ $sort: { total: -1 } }
] )
  • A sequência de estágios $unionWith recupera documentos das coleções especificadas para o pipeline:

  • O estágio $group agrupa pelo item campo e usa $sum para calcular a quantidade total de vendas por item.

  • O estágio $sort ordena os documentos total em ordem decrescente.

Resultado do pipeline:

{ "_id" : "Cookies", "total" : 1720 }
{ "_id" : "Chocolates", "total" : 1250 }
{ "_id" : "Nuts", "total" : 510 }
{ "_id" : "Pie", "total" : 395 }
{ "_id" : "Cheese", "total" : 350 }

Você pode usar $unionWith para realizar uma união com documentos especificados no campo pipeline. Ao especificar um estágio $documents no campo pipeline, você realiza uma união com documentos que não estão armazenados em uma coleção separada.

Criar uma coleção cakeFlavors:

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

A seguinte operação $unionWith executa uma união com documentos especificados no campo pipeline $documents :

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

Saída:

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

A partir do MongoDB 8.0, os namespaces em subpipelines dentro $lookup e $unionWith são validados para garantir o uso correto dos campos from e coll:

  • Por $lookup, omita o campo from se você usar um subpipeline com um estágio que não exija uma coleção especificada. Por exemplo, um estágio $documents.

  • Da mesma forma, para $unionWith, omita o campo coll.

Comportamento inalterado:

  • Para um $lookup que começa com um estágio para uma coleção, por exemplo, um subpipeline $match ou $collStats, você deve incluir o campo from e especificar a coleção.

  • Da mesma forma, para $unionWith, inclua o campo coll e especifique a coleção.

O cenário a seguir mostra um exemplo.

Criar uma coleção cakeFlavors:

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

A partir do MongoDB 8.0, o exemplo a seguir retorna um erro porque contém um campo coll inválido :

db.cakeFlavors.aggregate( [ {
$unionWith: {
coll: "cakeFlavors",
pipeline: [ { $documents: [] } ] }
} ] )

Nas versões do MongoDB anteriores a 8.0, o exemplo anterior é executado.

Para um exemplo com um campo coll válido, consulte Resultados duplicados.

Voltar

$sortByCount