$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
Definição
Sintaxe
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 |
---|---|---|
Obrigatório se | A collection or visualização cujos resultados de pipeline que você deseja incluir no conjunto de resultados. Se você omitir o campo | |
Obrigatório se | Um pipeline de agregação para aplicar aos documentos de entrada.
O pipeline não pode incluir os estágios e. A partir de |
A operação $unionWith
corresponderia à seguinte declaração SQL:
SELECT * FROM Collection1 WHERE ... UNION ALL SELECT * FROM Collection2 WHERE ...
Considerações
Resultados duplicados
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" }
$unionWith
uma collection fragmentada
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" } } ])
Agrupamentos
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.
Suporte do Atlas Search
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
Restrições | Descrição |
---|---|
Um pipeline de agregação não pode usar | |
Collection fragmentada | Se o estágio |
O pipeline $unionWith não pode incluir o | |
O pipeline $unionWith não pode incluir o |
Exemplos
Criar relatórios de vendas a partir da união de collections de dados anuais
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.
Preencher dados de amostra
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 } ] ) 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 } ] ) 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 } ] ) 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 } ] )
Relatório 1: todas as vendas por ano e lojas e itens
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
eitem
.
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 }
Relatório 2: vendas agregadas por itens
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 peloitem
campo e usa$sum
para calcular a quantidade total de vendas poritem
.O estágio
$sort
ordena os documentostotal
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 }
Crie uma união com documentos especificados
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 } ]
Namespaces em Subpipelines
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 campofrom
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 campocoll
.
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 campofrom
e especificar a coleção.Da mesma forma, para
$unionWith
, inclua o campocoll
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.