MongoDB を使用して 2つのコレクションを 1つのコレクションに結合する
- MongoDB を使用して、2つのコレクションを 1つのコレクションに結合する
-
$lookup
集計ステージを使用して、2つのコレクションを 1つに結合する -
pipeline
演算子を使用して、指定された条件に基づいて 2つのコレクションを 1つに結合する -
結果のドキュメントに添付する前に、
$unwind
演算子を使用してフラットアレイにする -
集計クエリの
$project
フィルタステージを使用して、2つのコレクションを 1つに結合する - Compass(MongoDB のグラフィカルインターフェイス)を使用して 2つのコレクションに参加する
今日は、$lookup
集計ステージ、pipeline
および $unwind
演算子、$project
フィルターステージ、および MongoDB Compass を使用して、2つのコレクションを 1つのコレクションに結合します。
MongoDB を使用して、2つのコレクションを 1つのコレクションに結合する
MongoDB を使用して、2つのコレクションを 1つのコレクションに結合するためのさまざまなアプローチがあります。それらのいくつかを以下に示します。これについては、このチュートリアルで説明します。
$lookup
集計ステージを使用して、2つのコレクションを結合しますpipeline
演算子を使用して、指定された条件に基づいて 2つのコレクションを結合します$unwind
演算子を使用して、結果のドキュメントに添付する前にアレイをフラット化します- 集計クエリで
$project
フィルターステージを使用して、2つのコレクションを結合します - コンパス(MongoDB のグラフィカルインターフェイス)を使用して 2つのコレクションを結合します
上記のすべてのシナリオでは、ドキュメント(MySQL のレコードと同じ)が入力された 2つのコレクション(MySQL のテーブルと同じ)を含むデータベースが必要です。次のクエリを使用してこれを実行しました。あなたもそうすることができます。
users
データベースに存在する usersInformation
と userAddress
という名前の 2つのコレクションを作成します。さらに、次のようにドキュメントを入力します。
データベースとコレクションを作成します。
> use users
> db.createCollection('userInformation')
> db.createCollection('userAddress')
userInformation
コレクションに 2つのドキュメントを入力します。
> db.userInformation.insertMany(
[
{
fullname: 'Mehvish Ashiq',
age: 30,
gender: 'Female',
nationality: 'Pakistani'
},
{
fullname: 'James Daniel',
age: 45,
sex: 'male',
nationality: 'Canadian'
}
]
)
userAddress
コレクションに 2つのドキュメントを入力します。
> db.userAddress.insertMany(
[
{
fullname: 'Mehvish Ashiq',
block_number: 22,
street: 'Johar Town Street',
city: 'Lahore'
},
{
fullname: 'James Daniel',
block_number: 30,
street: 'Saint-Denis Street',
city: 'Montreal'
}
]
)
insertMany()
関数を使用して、複数のドキュメントを挿入します。これで、以下のコマンドを使用して、両方のコレクションのデータを確認できます。
次のコードスニペットでは、pretty()
メソッドがクリーンでフォーマットされた出力を示しています。これはシェルで簡単に理解できます。
userInformation
からのドキュメントを表示します。
> db.userInformation.find().pretty()
出力:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian"
}
userAddress
からドキュメントを表示します。
> db.userAddress.find().pretty()
出力:
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
$lookup
集計ステージを使用するには、両方のコレクションが同じデータベースに存在する必要があります。両方のコレクションの準備ができたら、さまざまなクエリを使用して、シナリオに応じて両方のコレクションのデータを結合できます。
$lookup
集計ステージを使用して、2つのコレクションを 1つに結合する
サンプルコード:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
}
]).pretty();
出力:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
]
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
]
}
MongoDB データベースでは、$lookup
aggregate stageが他のコレクションとの左外部結合を実行し、結合されたドキュメントから情報(データ)をフィルタリングします。たとえば、クエリを使用して、すべてのユーザーの情報とそのアドレスを取得します。
$lookup
関数は 4つのフィールドを受け入れます。最初は from
フィールドで、他のコレクションと結合されることになっているコレクションを指定します。
2 番目は localField
フィールドです。これは、from
フィールドで指定されたコレクションの入力ドキュメントの属性(フィールド)の 1つです。
これは、コレクションのドキュメントから localField
から foreignField
への照合を実行するために使用されます。
同様に、foreignField
という名前の 3 番目のフィールドも、コレクションのドキュメントから foreignField
から localField
への等価一致を実行します。
4 番目のフィールド as
に新しいアレイの名前を書き込みます。 $lookup
集計ステージについては、次の説明を参照してください。
pipeline
演算子を使用して、指定された条件に基づいて 2つのコレクションを 1つに結合する
サンプルコード:
> db.userInformation.aggregate([{
$lookup:{
from: 'userAddress',
let: {full_name: '$fullname'},
pipeline: [{
$match: {
$expr: {
$eq: ['$fullname', '$$full_name']
}
}
}],
as: 'addressInfo'
}
}]).pretty()
出力:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"addressInfo" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
]
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"addressInfo" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
]
}
特定の条件に基づいて 2つのコレクションを結合する場合(MySQL で WHERE
句を使用するのと同じように)、$lookup
で pipeline
演算子を使用できます。
たとえば、userAddress
の fullname
が userInformation
の fullname
と等しいコレクションに参加しています。
結果のドキュメントに添付する前に、$unwind
演算子を使用してフラットアレイにする
サンプルコード:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
}
]).pretty();
出力:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
}
$unwind
演算子は、結果のドキュメントにアタッチする前に、アレイをフラット化するだけです。 $unwind
演算子の基本的な違いは、単一の要素を持つ配列を、要素自体であるフラット化されたオブジェクトに変換することです。
この要素の名前は変更されないことに注意してください。これは、要素が配列の形式であった場合と同じになります。
$unwind
演算子を使用して、または使用せずに上記のクエリを実行し、address
フィールドを確認します。
集計クエリの $project
フィルタステージを使用して、2つのコレクションを 1つに結合する
$project
を使用してコレクションに参加する前に、その重要性を理解しましょう。たとえば、userAddress
という名前のコレクション全体を userInformation
に結合したくない場合は、city
フィールドと street
フィールドのみを結合する必要があります。
その場合、$addFields
ステージを使用する必要があります。このステージを使用して、任意のフィールドまたは複数のフィールドをアレイ/オブジェクトからドキュメントのルートレベルに結合/割り当てます。
したがって、次のクエリを実行して、userAddress
コレクションから city
と street
を取得します。
サンプルコード:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
},
{
$addFields: {
street: '$address.street',
city: '$address.city'
}
}
]).pretty();
出力:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
},
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
},
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
上記の出力に注意深く焦点を合わせます。通り
と都市
を取得していますか?はい、ドキュメントのルートレベルで street
と city
を取得していますが、現在必要のない address
オブジェクトもあります。
ここで、$project
フィルターステージが登場します。結果のドキュメントに含める必要のあるフィールドを指定します。
理解を深めるには、次のクエリを参照してください。
サンプルコード:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
},
{
$addFields: {
street: '$address.street',
city: '$address.city'
}
},
{
$project: {
fullname: 1,
age: 1,
gender: 1,
street: 1,
city: 1
}
}
]).pretty();
出力:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
ご覧のとおり、現在 address
オブジェクトはありませんが、その 2つのフィールド(street
と city
)がドキュメントのルートレベルに割り当てられています。
Compass(MongoDB のグラフィカルインターフェイス)を使用して 2つのコレクションに参加する
グラフィカルインターフェイスを使用した集計は簡単です。 $lookup
集計段階では、次の手順に従うだけで済みます。
-
MongoDBCompass
を開き、サーバーに接続します。 -
必要に応じて、新しいデータベースと 2つのコレクションを作成します。Mongo シェルを使用して作成したものと同じデータベースとコレクションを使用します。
-
次のように表示されるコレクションを開きます。
-
プロジェクトの要件に従ってステージを追加します。
$lookup
集計ステージを追加します。$lookup
フィールドを更新して、右側に目的の結果を確認してください。
関連記事 - MongoDB Collection
- MongoDB Truncate コレクション
- MongoDB コレクション内のすべてのドキュメントに新しいフィールドを追加する
- MongoDB でのコレクションのドロップまたは削除
- NodeJS を使用して MongoDB にコレクションが存在するかどうかを確認する
- MongoDB の同じデータベース内のコレクションをコピーする