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と同じフィールドがありませんでした コレクションですが、それでも問題ありません。それでも機能しました。