MongoDBで結合操作を実行するためのシンプルなテクニック
'MongoDB結合操作のシンプルなテクニック'
はじめに
データベースの人々はJOINSに非常に精通しています。複数のテーブルからデータを取得する場合、主キーと外部キーに基づいてテーブルを結合することがよくあります。この記事では、MongoDBで結合操作を行うためのシンプルなテクニックを学びましょう。
上記の図は、組織のリレーショナルデータベーススキーマの図解です。これらのブロックは、特定の種類のデータ(学生/教授/従業員)を格納するテーブルであり、線と矢印は共通のキーを使用してテーブル間の関係を表します。テーブル間の関係に基づいて結合を行うことができます。
例えば、組織では、従業員、部門、プロジェクトなどのデータを格納するための別々のテーブルがあります。従業員の詳細と彼らがどの部門とプロジェクトで働いているかを取得するには、テーブル間で結合を行い必要なデータを取得する必要があります。
同様に、大学では、学生と教授のデータを格納するための別々のテーブルがあるかもしれません。特定の学生を教えている教授を見つけるには、テーブル間で結合を行う必要があります。
学習目標
このチュートリアルでは、MongoDBでさまざまな結合操作(内部結合、外部結合、右結合、左結合)をどのように実行できるかを見ていきます。
この記事は、Data Science Blogathonの一環として公開されました。
異なるタイプの共通結合操作の理解
A. SQLと異なる種類の結合
私たちの大部分はSQLデータベースの知識を持っています。そこでは、以下で説明する4つの主要な結合操作をよく行います。
1. 内部結合:両方のテーブルで共通のキーを持つ行のみが結果のテーブルに存在します。
内部結合を実行した結果、Roll Noキーが両方に共通している行のみが返されることがわかります。
2. 左外部結合:左側のテーブルのすべての行(マッチングキー+非マッチングキー)が結果のテーブルにあります。したがって、結果のテーブルには、右側のテーブルからのマッチングキーのみの行があります。マッチングしないキーがある場合は、それを排除することはできません。
左結合を実行した後、左側のテーブルのすべての列があります。 Deepak K.のClass Rankは右側のテーブルに存在しないため、nullで埋めます。左側のテーブルとRoll Noが一致する右側のテーブルのレコードのみが結果に存在することが話し合われました。そのため、右側のテーブルのタプル(3D5RE、16)は結果にありません。
3. 右外部結合:左外部結合の逆です。結果のテーブルには右側のテーブルのすべての行があり、左側のテーブルとの一致するキーのみがあります。
右のテーブルから予想通りのすべてのレコード/タプルが結果に存在していますが、左のテーブルからのレコード(2A3AS、Deepak K.、87)は存在しません。
4. フルアウタージョイン: 両方のテーブルのすべての行(一致するキーと一致しないキーの両方)が結果のテーブルに存在します。
予想通り、結果には両方のテーブルのすべてのタプルがあります。値が存在しない場所はnullで埋められます。
B. MongoDBの簡単な紹介
MongoDBはドキュメントベースのNoSQLデータベースです。NoSQLデータベースは、大規模な非リレーショナルで構造化されていない頻繁に変更されるデータの保存に適しています。以下の2つのブログにはMongoDBの比較と操作があります。
- MongoDBの紹介
- MongoDBでのCRUD操作
MongoDBデータベースは1つ以上のコレクションで構成されます。コレクションはSQLデータベースのテーブルに相当します。各コレクションには1つ以上のドキュメントが含まれています。したがって、ドキュメントはSQLデータベースのテーブルの行またはタプルと考えることができます。データはMongoDB内部でBSON(バイナリJSON形式)として格納されます。
MongoDBでのジョイン操作
では、異なるジョイン操作がMongoDBのコレクションでどのように実行されるかを見てみましょう。
MarksとRankの2つのテーブルを、それぞれのコレクションのドキュメントとして変換します。これらのコレクションをMongoDB内のSchoolという名前のデータベースに保存します。
左外部結合
コード:
db.Marks.aggregate([{$lookup:{from:"Rank",localField:"Roll No",
foreignField:"Roll No",as:"Ranks"}}])
[出力を拡大]
各学生のランクの詳細が彼らのドキュメントに追加されていることがわかります。 Deepakの場合、Rankテーブルにランクの詳細がないので、彼のRanksフィールドは空のリストです。
次に使用されるパラメータを理解しましょう:
- ここでMarksは左のテーブルです。
- $lookupは、2つのコレクション間でのジョインを実行するための集計関数/演算子です。
- lookupの中で、fromはジョインを実行したいコレクションを示します。つまり、右のテーブル(コレクション)です。この場合、Rankが右のコレクションです。
- localFieldは、ジョインを実行するために左のコレクションからマッチングキーとして使用されるフィールドを示します。右のコレクションのフィールドで一致するキーが見つかった場合、結果のフィールド(ここでは)は空でなく、それ以外の場合は空です(例ではDeepakの場合)。
- foreignFieldは、右のコレクションのキーです。
- asは、ジョインによって生成される結果のテーブル/コレクションに格納される右のテーブル(コレクション)の詳細のフィールドの名前を示します。
- この場合、新しいフィールドRanksを結果のテーブル(コレクション)に追加します。このフィールドには対応する学生のランクの詳細が含まれます。
もう一つ覚えておくべきことは、MongoDBでは$lookupは左結合のみを実行でき、他の種類の結合には特定の構文が存在しないということです。したがって、他の種類の結合は異なるトリックと操作を使用して導出する必要があります
右外部結合
右結合は、左結合とは逆の動作です。マッチしたレコードに加えて、右側のコレクション/テーブルの非マッチングレコードも結果のコレクション/テーブルに存在する必要があります。
右結合を行うための簡単な方法は、2つのコレクションの位置を変更するだけです。その結果、右のコレクションが左になり、逆もまた同様です。これにより、結合には右テーブルのすべての行(マッチング+非マッチング)が含まれるようになります。
コード :
db.Rank.aggregate([{$lookup:{from:"Marks", localField:"Roll No",
foreignField:"Roll No", as:"Marks_Students"}}])
[出力を拡大]
内部結合
簡単なトリックを使用して、内部結合を効率的に実行できます!!!左結合を行い、asフィールドが空でないレコードをすべて削除します。その結果、両方のテーブル(コレクション)にキーが存在するレコードのみが残ります。
コード :
db.Rank.aggregate([{$lookup:{from:"Marks", localField:"Roll No", foreignField:"Roll No",
as: "Marks_Students"}}, {$match:{"Marks_Students":{$ne:[]}}}])
[出力を拡大]
上記の結果では、両方のコレクションのキーが一致するレコードのみが表示されます。ここで{$match:{“Marks_Students”:{$ne:[]}}}は、Marks_Studentsフィールドが[](空のリスト)ではないレコードのみにマッチするよう指示しています
フル外部結合
フル外部結合は少し複雑ですが、3つの操作の組み合わせで設計しました。初めて見ると混乱するかもしれませんが、理解を深めるために何度も読んでみてください。
ステップ1:Marks(左のコレクション)とRank(右のコレクション)の左結合を行い、結果レコード全体にMarksという空のフィールドを追加し、新しいコレクションJ2に結果を送信/出力します。
コード:
db.Marks.aggregate([{$lookup:{from:"Rank",localField:"Roll No", foreignField:"Roll No", as:"Rank"}},
{$addFields:{Marks:[]}},{$out:"J2"}])
[出力を拡大]
したがって、新しいコレクションは上記のスクリーンショットのようになります。
- {$addFields:{Marks:[]}} -> すべてのレコードに追加のフィールドMarksを追加します。
- {$out:“J2″}] -> 結果を新しいコレクションJ2に出力/送信します。
したがって、当然のことながら、私たちのデータベースSchoolには3つのコレクションが含まれています-
Marks、Rank、J2
ステップ2: Rank を左コレクションとして考慮し、Marks と Rank の右結合を行い、結果を J2 コレクションに追加します。
コード:
db.Rank.aggregate([{$lookup:{from:"Marks",localField:"Roll No",foreignField:"Roll No",
as:"Marks"}},{$merge:"J2"}])
[出力を拡大]
[出力を拡大]
システムが新しい出力をステップ1の古い出力の下に追加する方法に注目してください。
ステップ3:
マッチングフィールドが []( 空 ) の集計結果のみを保持し、他のレコードは破棄します。この方法で重複を削除し、両方のコレクション/テーブルからすべての異なるフィールドのみが結果に含まれます。 (ステップ2の出力には重複があることに気づいたかもしれません、例:Nikitaのレコードが2つあります)
最後に、集計結果から空の Marks フィールドを削除します。このフィールドは空であり、表示する必要がないためです。その目的は重複を削除することでした。
コード:
db.J2.aggregate([{$redact:{$cond:[{$eq:["$Marks",[]]},"$KEEP","$PRUNE"]}},
{$unset:”Marks”}])
[出力を拡大]
最終的に目的の出力が得られました。両方のテーブル(コレクション)で一致したレコードおよび片方のテーブル(コレクション)に存在する他のレコードがすべて含まれています。 (Marksの中のDeepak、およびRankの中のロール番号3D5REなど)
結論
したがって、MongoDBの左結合からさまざまな種類の結合を成功裏に導出しました。要約すると、MongoDBでの左結合を実行するための直接の構文しか利用できません。他のタイプの結合は、左結合に対して異なる操作とテクニックを適用することで導出する必要があります。たとえば、内部結合の場合は空の as フィールドがあるコレクションを削除するなどです。
これらの結合を導出する際に気付いたこと:
- 集計クエリの良い知識が必要です。
- 中間結果を注意深く観察して次のステップを決定する必要があります。
- 結合を導出する他の(さらに良い)方法があるかもしれません。
もっと良い方法をご存知の場合は、コメントで共有してください。
要点
- MongoDBでは、左結合操作のみが直接の構文として利用できます。
- 右結合は、構文のコレクションの位置を変更することで導出します。
- 内部結合は、まず左結合を実行し、空の as フィールドを削除することで導出します。
- 外部結合は、一連の単純で巧妙な操作で実行できます。
よくある質問
参考文献
- MongoDBドキュメントのLookup
- MongoDB公式ドキュメントの$redact
- MongoDB Inner Join 101: Syntax & Example Simplified by Samuel Salimon
この記事のメディアはAnalytics Vidhyaの所有ではなく、著者の裁量で使用されています。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles