$unionWith(集計)
項目一覧
定義
構文
$unionWith
ステージの構文は次のとおりです。
{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }
指定したコレクションの全ドキュメントを処理せずに含めるには、簡略化された形式を使用できます。
{ $unionWith: "<collection>" } // Include all documents from the specified collection
$unionWith
ステージは、次のフィールドを持つドキュメントを取得します。
フィールド | 必要性 | 説明 |
---|---|---|
| ||
| 入力ドキュメントに適用する集計パイプライン。
パイプラインには |
$unionWith
操作は、次の SQL ステートメントに対応します。
SELECT * FROM Collection1 WHERE ... UNION ALL SELECT * FROM Collection2 WHERE ...
Considerations
重複した結果
前のステージと $unionWith
ステージから組み合わせた結果には重複が含まれる場合があります。
たとえば、suppliers
コレクションと 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" }, ])
次の集計は、suppliers
コレクションと warehouse
コレクションの state
フィールドのプロジェクション結果を組み合わせたものです。
db.suppliers.aggregate([ { $project: { state: 1, _id: 0 } }, { $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} } ])
結果セットには重複が含まれています。
{ "state" : "Texas" } { "state" : "Colorado" } { "state" : "Rhode Island" } { "state" : "California" } { "state" : "Colorado" } { "state" : "Florida" }
重複を削除するには、$group
ステージを追加して、state
フィールドでグループ化します。
db.suppliers.aggregate([ { $project: { state: 1, _id: 0 } }, { $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} }, { $group: { _id: "$state" } } ])
結果セットには重複が含まれなくなりました。
{ "_id" : "California" } { "_id" : "Texas" } { "_id" : "Florida" } { "_id" : "Colorado" } { "_id" : "Rhode Island" }
$unionWith
シャーディングされたコレクション
$unionWith
ステージが $lookup パイプラインの一部である場合、$unionWith
coll はシャーディングできません。たとえば、次の集計操作では、inventory_q1
コレクションをシャーディングできません。
db.suppliers.aggregate([ { $lookup: { from: "warehouses", let: { order_item: "$item", order_qty: "$ordered" }, pipeline: [ ... { $unionWith: { coll: "inventory_q1", pipeline: [ ... ] } }, ... ], as: "stockdata" } } ])
照合
db.collection.aggregate()
にcollation
ドキュメントが含まれている場合、その照合が操作に使用され、他の照合は無視されます。
db.collection.aggregate()
にcollation
ドキュメントが含まれていない場合、 db.collection.aggregate()
メソッドは、 db.collection.aggregate()
が実行される最上位のコレクションやビューの照合を使用します。
$unionWith coll がコレクションの場合、その照合は無視されます。
$unionWith coll がビューの場合、その照合は最上位のコレクションやビューの照合と一致する必要があります。そうでない場合はエラーとなります。
Atlas Search サポート
MongoDB 6.0 以降では、 $unionWith
パイプラインで Atlas Search $search
または $searchMeta
ステージを指定して、Atlas クラスター上のコレクションを検索できます。$search
または $searchMeta
ステージは、 $unionWith
パイプライン内の最初のステージである必要があります。
[{ "$unionWith": { "coll": <collection-name>, "pipeline": [{ "$search": { "<operator>": { <operator-specification> } }, ... }] } }]
[{ "$unionWith": { "coll": <collection-name>, "pipeline": [{ "$searchMeta": { "<collector>": { <collector-specification> } }, ... }] } }]
$search
とともに$unionWith
を使用した例えについては、Atlas Search チュートリアルの「$unionWith を使用して Atlas Search $検索クエリを実行する」を参照してください。
制限事項
制限事項 | 説明 |
---|---|
集計パイプラインでは、トランザクション内で | |
シャーディングされたコレクション |
|
$unionWithパイプラインには | |
$unionWithパイプラインには |
例
年間データ コレクションの和集合から売上レポートを作成
次の例では、$unionWith
ステージを使用してデータを結合し、複数のコレクションから結果を返します。これらの例では、各コレクションに 1 年間の販売データが含まれています。
サンプル データの入力
次のドキュメントを使用して
sales_2017
コレクションを作成します。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 } ] ) 次のドキュメントを使用して
sales_2018
コレクションを作成します。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 } ] ) 次のドキュメントを使用して
sales_2019
コレクションを作成します。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 } ] ) 次のドキュメントを使用して
sales_2020
コレクションを作成します。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 } ] )
レポート 1: 年別、店舗別、商品別全売上
次の集計では、四半期および店舗ごとのすべての売上を一覧表示する年間売上レポートが作成されます。 パイプラインは$unionWith
を使用して次の 4 つのすべてのコレクションのドキュメントを結合します。
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 } } ] )
具体的には、集計パイプラインでは次のものが使用されます。
$set
ステージで、_id
フィールドを更新して年を含めます。4 つのコレクションのすべてのドキュメントを結合するための
$unionWith
ステージのシーケンス。それぞれのドキュメントで$set
ステージも使用します。$sort
ステージで、_id
(年)、store
、item
で並べ替えます。
パイプライン出力は次のようになります。
{ "_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 }
レポート 2: 品目別売上集計
次の集計では、品目ごとの販売数量を一覧表示する販売レポートが作成されます。パイプラインは $unionWith
を使用して 4 年間すべてのドキュメントを結合します。
db.sales_2017.aggregate( [ { $unionWith: "sales_2018" }, { $unionWith: "sales_2019" }, { $unionWith: "sales_2020" }, { $group: { _id: "$item", total: { $sum: "$quantity" } } }, { $sort: { total: -1 } } ] )
$unionWith
ステージのシーケンスは、指定されたコレクションからパイプラインにドキュメントを検索します。$group
ステージはitem
フィールドでグループ化し、$sum
を使用してitem
ごとの合計販売数量を計算します。$sort
ステージでは、ドキュメントをtotal
の降順で並べ替えます。
パイプライン出力は次のようになります。
{ "_id" : "Cookies", "total" : 1720 } { "_id" : "Chocolates", "total" : 1250 } { "_id" : "Nuts", "total" : 510 } { "_id" : "Pie", "total" : 395 } { "_id" : "Cheese", "total" : 350 }
指定されたドキュメントとの Union の作成
$unionWith
を使用して、 pipeline
フィールドに指定したドキュメントとの和集合を実行できます。 pipeline
フィールドに$documents
ステージを指定すると、別のコレクションに保存されていないドキュメントとの和集合が実行されます。
コレクション cakeFlavors
を以下ように作成します。
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
次の$unionWith
操作は、 pipeline
$documents
フィールドに指定されたドキュメントとの和集合を実行します。
db.cakeFlavors.aggregate( [ { $unionWith: { pipeline: [ { $documents: [ { _id: 4, flavor: "orange" }, { _id: 5, flavor: "vanilla", price: 20 } ] } ] } } ] )
出力:
[ { _id: 1, flavor: 'chocolate' }, { _id: 2, flavor: 'strawberry' }, { _id: 3, flavor: 'cherry' }, { _id: 4, flavor: 'orange' }, { _id: 5, flavor: 'vanilla', price: 20 } ]
サブパイプラインの名前空間
MongoDB 8.0 以降では、from
フィールドと coll
フィールドが正しく使用されるように、$lookup
と $unionWith
内のサブパイプラインの名前空間が検証されます。
$lookup
の場合、指定されたコレクションを必要としないステージを持つサブパイプラインを使用する場合は、from
フィールドを省略する(例:$documents
ステージ)。同様に、
$unionWith
の場合、coll
フィールドを省略する。
変更されていない動作:
コレクションのステージで開始される
$lookup
の場合(例:$match
サブパイプラインまたは$collStats
サブパイプライン)、from
フィールドを含め、コレクションを指定する必要があります。同様に、
$unionWith
の場合は、coll
フィールドを含め、コレクションを指定します。
次のシナリオは例です。
コレクション cakeFlavors
を以下ように作成します。
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
MongoDB 8.0 以降、次の例では、無効な coll
フィールドが含まれているためエラーが返されます。
db.cakeFlavors.aggregate( [ { $unionWith: { coll: "cakeFlavors", pipeline: [ { $documents: [] } ] } } ] )
8.0 より前の MongoDB バージョンでは、前の例が実行されます。
有効な coll
フィールドの例については、「重複した結果」を参照してください。