参照の配列を使用して、異なるタイプの関連ドキュメントを 1 つのコレクションにグループ化するデータモデルを作成します。単一コレクション パターン は、データのコピーが 1 つだけの多対多の関係をモデル化する場合に特に役立ちます。このパターンにより、重複のコストが懸念されるユースケースでデータの重複を減らすことができます。
次の特性が、単一コレクション パターンを定義します。
頻繁にアクセスするドキュメントをすべて 1 つのコレクションにまとめて保存します。
ドキュメント間の関係を各ドキュメント内にポインターまたは構造体として保存します。
フィールドまたは配列のインデックスを介して、ドキュメント間の関係をマッピングします。このインデックスでは、データベース結合操作を使用せずに、1 回のクエリで関連ドキュメントを取得できます。
高速操作、低レイテンシ要件、頻繁に書込み操作を伴うシステムをモデル化する場合は、単一コレクション パターンの使用を検討してください。ドキュメントを大きな埋め込みドキュメントではなく小さな部分に分割することで、データベースは書込み操作を少なくし、パフォーマンスを向上させることができます。
このタスクについて
次の例では 、アプリケーションを使用して、学生が学期に登録するクラスのステータスを確認できるようにします。システムでは、current_topic、upcoming_session_summary、next_class_time など、各クラスの複数のフィールドを頻繁に更新する必要がある場合があります。同じクラスを取得している複数の学生の情報が重複しないようにするため、学生とクラスを同じコレクション内の個別のドキュメントエンティティとして保持する必要があります。
例
クラスと学生の次の例スキーマを検討します。関係をモデル化するために、クラスと学生のドキュメントには links 配列が含まれています。この配列には、学生とクラスのエンティティ間の関係を参照ための doc_type フィールドと target フィールドが含まれています。
クラスドキュメント:
{ _id : "CS101-001", doc_type : "class", class_name : "Introduction to Programming", course_id : "CS101", instructor : { name : "Dr. Emily Smith", email : "emily.smith@example.com", office_hours : "Tuesdays and Thursdays 2:00 PM - 4:00 PM" }, semester : "Spring 2025", schedule : [ { day_time : "Monday 10:00 AM - 11:30 AM", location : "Room 101, Science Building" }, { day_time : "Wednesday 10:00 AM - 11:30 AM", location : "Room 101, Science Building" }, { day_time : "Friday 10:00 AM - 11:30 AM", location : "Room 101, Science Building" } ], current_topic : "Loops and Iterations", next_class_time : "2025-01-09T10:00:00Z", upcoming_session_summary : "We will explore different types of loops (for, while) and how to use them effectively in Python.", links : [ { target : "CS101-001", doc_type : "class" }, { target : "S10023", doc_type : "student" }, { target : "S12345", doc_type : "student" }, ... { target : "S12355", doc_type : "student" } ] }
学生ドキュメント:
{ _id : "S12345", doc_type : "student", name : "Jane Doe", major : "Computer Science", semester : "Spring 2025", registered_classes : [ { course_id : "CS101", class_instance_id : "CS101-001", class_name : "Introduction to Programming" }, { course_id : "MATH201", class_instance_id : "MATH201-002", class_name : "Calculus II" } ], links : [ { target : "CS101-001", doc_type : "class" }, { target : "MATH201-002", doc_type : "class" }, { target : "S12345", doc_type : "student" } ] }
クエリを最適化するには、次のように linksフィールドをインデックス。
db.students_classes.createIndex({ "links.target": 1, "links.doc_type": 1 })
結合操作を実行しなくても、学生の情報と学生が取得するすべてのクラスをクエリできます。
db.students_classes.find({ "links.target": "S12345" })
同様に、特定のクラスに登録されているすべての生徒をクエリできます。
db.students_classes.find({ "doc_type": "student", "links.target": "CS101-001" })