SQLに精通している場合は、UNION
について知っているかもしれません。 2つのクエリの結果を1つの結果セットに連結する句。特に、UNION ALL
重複が含まれます。
MongoDBでは、$unionWith
を使用できます UNION ALL
と同じ効果を達成するための集約パイプラインステージ を生成します。 $unionWith
ステージは、2つのコレクションの結合を実行します。これは、2つのコレクションからのパイプライン結果を1つの結果セットに結合します。そして、それは重複を含みます。
例
2つのコレクションを作成するとします。 cats
と呼ばれるもの もう1つはdogs
と呼ばれます 。そして、次のドキュメントを挿入します:
db.cats.insertMany([
{ _id: 1, name: "Fluffy", type: "Cat", weight: 5 },
{ _id: 2, name: "Scratch", type: "Cat", weight: 3 },
{ _id: 3, name: "Meow", type: "Cat", weight: 7 }
])
db.dogs.insertMany([
{ _id: 1, name: "Wag", type: "Dog", weight: 20 },
{ _id: 2, name: "Bark", type: "Dog", weight: 10 },
{ _id: 3, name: "Fluffy", type: "Dog", weight: 40 }
])
これらのコレクションに対してクエリを実行し、$unionWith
を使用できるようになりました。 各クエリの結果を組み合わせるステージ。
例:
db.cats.aggregate( [
{ $set: { _id: "$_id" } },
{ $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "$_id" } } ] } },
{ $sort: { type: 1, weight: -1, name: 1 } }
] )
結果:
{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 } { "_id" : 1, "name" : "Fluffy", "type" : "Cat", "weight" : 5 } { "_id" : 2, "name" : "Scratch", "type" : "Cat", "weight" : 3 } { "_id" : 3, "name" : "Fluffy", "type" : "Dog", "weight" : 40 } { "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 } { "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }
この例では、各ドキュメントにcat
のいずれかのタイプフィールドがあります またはdog
したがって、どのドキュメントがどのコレクションからのものであるかは非常に明白です。
ただし、ドキュメントにタイプフィールドがない場合、1つのコレクションが終了し、別のコレクションが開始する場所を特定するのは困難です。この場合、$set
で文字列リテラルを使用できます コレクション名を表すステージ。
例:
db.cats.aggregate( [
{ $set: { _id: "cat" } },
{ $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "dog" } } ] } },
{ $sort: { type: 1, weight: -1, name: 1 } }
] )
結果:
{ "_id" : "cat", "name" : "Meow", "type" : "Cat", "weight" : 7 } { "_id" : "cat", "name" : "Fluffy", "type" : "Cat", "weight" : 5 } { "_id" : "cat", "name" : "Scratch", "type" : "Cat", "weight" : 3 } { "_id" : "dog", "name" : "Fluffy", "type" : "Dog", "weight" : 40 } { "_id" : "dog", "name" : "Wag", "type" : "Dog", "weight" : 20 } { "_id" : "dog", "name" : "Bark", "type" : "Dog", "weight" : 10 }
コレクション間での並べ替え
前の例では、猫と犬は2つの異なるグループに分けられるように分類されていました。最初に猫、次に犬。これは主に、type
で並べ替えたために発生しました フィールドファースト。
ただし、他のフィールドで並べ替えることができるため、猫と犬が組み合わされる可能性があります。
例:
db.cats.aggregate( [
{ $set: { _id: "cat" } },
{ $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "dog" } } ] } },
{ $sort: { name: 1 } }
] )
結果:
{ "_id" : "dog", "name" : "Bark", "type" : "Dog", "weight" : 10 } { "_id" : "cat", "name" : "Fluffy", "type" : "Cat", "weight" : 5 } { "_id" : "dog", "name" : "Fluffy", "type" : "Dog", "weight" : 40 } { "_id" : "cat", "name" : "Meow", "type" : "Cat", "weight" : 7 } { "_id" : "cat", "name" : "Scratch", "type" : "Cat", "weight" : 3 } { "_id" : "dog", "name" : "Wag", "type" : "Dog", "weight" : 20 }
プロジェクション
$project
を使用できます パイプラインの次のステージに渡されるフィールドを指定するステージ。たとえば、クエリによって返されるフィールドの数を減らすことができます。
例:
db.cats.aggregate( [
{ $project: { name: 1, _id: 0 } },
{ $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} }
] )
結果:
{ "name" : "Fluffy" } { "name" : "Scratch" } { "name" : "Meow" } { "name" : "Wag" } { "name" : "Bark" } { "name" : "Fluffy" }
重複を削除
$group
を使用できます 結果から冗長な重複を排除するためのステージ。
たとえば、前のクエリでは、Fluffyという2匹のペットが返されました。 $group
を追加できます そのクエリをステージングして冗長な重複を排除し、1つのFluffyのみが返されるようにします。
db.cats.aggregate( [
{ $project: { name: 1, _id: 0 } },
{ $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} },
{ $group: { _id: "$name" } }
] )
結果:
{ "_id" : "Meow" } { "_id" : "Bark" } { "_id" : "Scratch" } { "_id" : "Wag" } { "_id" : "Fluffy" }
今回は、ふわふわが1つだけ返されます。
一致しない列
MongoDBの$unionWith
の利点の1つ SQLのUNION ALL
を超えています 一致しない列で使用できるということです。
SQL UNION
条項には次のものが必要です:
- どちらのクエリも同じ数の列を返します
- 同じ順序の列
- 一致する列は互換性のあるデータ型である必要があります
MongoDB $unionWith
ステージはこれらの制限を課しません。
したがって、$unionWith
を使用できます。 このようなことをするには:
db.cats.aggregate( [
{ $set: { _id: "$_id" } },
{ $unionWith: { coll: "employees", pipeline: [ { $set: { _id: "$_id" } } ] } },
{ $sort: { type: 1, salary: -1 } }
] )
結果:
{ "_id" : 2, "name" : "Sarah", "salary" : 128000 } { "_id" : 5, "name" : "Beck", "salary" : 82000 } { "_id" : 4, "name" : "Chris", "salary" : 45000 } { "_id" : 3, "name" : "Fritz", "salary" : 25000 } { "_id" : 1, "name" : "Fluffy", "type" : "Cat", "weight" : 5 } { "_id" : 2, "name" : "Scratch", "type" : "Cat", "weight" : 3 } { "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
この場合、cats
に参加しました employees
によるコレクション コレクション。 employees
コレクションには、cats
と同じフィールドがありませんでした コレクションですが、それでも問題ありません。それでも機能しました。