導入
MongoDBとMongooseでは、ドキュメント間のリレーションシップの管理は、スケーラブルで効率的なデータモデルを設計する上で重要な要素です。テーブルと外部キーを使用するリレーショナルデータベースとは異なり、MongoDBでは、関連データをドキュメントに埋め込むか、コレクション内のデータを参照するかを選択できます。それぞれのアプローチには長所と短所があり、適切な選択はアプリケーションの構造と要件によって異なります。.
このガイドでは、データを埋め込むタイミングと参照するタイミングについて、Mongoose で関係を効果的にモデル化するのに役立つ実用的な例とともに説明します。.
MongoDBにおける関係性の理解
MongoDBは、データの関係性を柔軟に管理できるNoSQLデータベースです。MongoDBでは、主に2つの方法で関係性を設計できます。
- 埋め込み: 関連データをドキュメントに保存します。.
- 参照: 関連データを別のコレクションに保存し、参照 (ObjectId) を使用してリンクします。.
埋め込みと参照の選択は、データ アクセス パターン、ドキュメント サイズ、互換性の要件、および関連データの更新頻度によって異なります。.
1. ドキュメントの埋め込み
埋め込みとは、関連データをネストされたオブジェクトまたは配列として親ドキュメントに直接保存することです。これは、頻繁に一緒にアクセスされ、1対多または1対多の関係を持つデータに最適です。.
埋め込みのメリット
- 単一ドキュメントへのアクセス: すべてのデータが 1 つのドキュメントに配置されるため、結合や追加のリクエストの必要性が軽減されます。.
- アトミック操作: 更新と読み取りはアトミックなので、データの一貫性を維持しやすくなります。.
- 早読み機能: 関連データが一緒に保存されるため、ドキュメントの取得が高速化され、追加のデータベース呼び出しが回避されます。.
埋め込み制限
- ドキュメントサイズの制限: MongoDB ドキュメントは 16 MB に制限されています。大規模なネストされた配列はすぐにこの制限に近づく可能性があります。.
- 更新時に繰り返します: ドキュメント内のネストされたデータを更新すると、データが重複し、不整合が発生する可能性があります。.
- 柔軟性が限られている: 埋め込みドキュメントは、特にデータが時間の経過とともに増大する場合、関係を照会する柔軟性が低くなります。.
例: ブログ投稿にコメントを埋め込む
ブログ アプリケーションでは、コメントは投稿に完全に関連付けられているため、投稿ドキュメントに直接コメントを埋め込むことができます。.
const mongoose = require("mongoose");
const commentSchema = new mongoose.Schema({
user: { type: String, required: true },
message: { type: String, required: true },
date: { type: Date, default: Date.now }
});
const postSchema = new mongoose.Schema({
title: { type: String, required: true },
content: { type: String, required: true },
comments: [commentSchema] // Embedding comments in the post
});
const Post = mongoose.model("Post", postSchema);この設定では、各投稿ドキュメントにコメントの配列が含まれているため、1 回のクエリで投稿とそのコメントを簡単に取得できます。.
2. 参照文書
参照(または正規化)では、関連データを別々のコレクションに保存し、ObjectId を使用してそれらをリンクします。これは、大規模なデータセットや、関連データを個別にクエリする必要がある場合に最適です。.
紹介のメリット
- データの再利用性: ユーザー プロファイルなどの共有データは、一度保存するだけで、複数のドキュメントから参照できます。.
- ドキュメント サイズの縮小: 参照によりドキュメント サイズが小さくなり、大きなネスト構造が回避されます。.
- スケーラビリティ: 参照により、データの増加に応じて柔軟性が提供され、多対多の関係をより効率的に管理できるようになります。.
紹介制限
- 複数のクエリ: 関連データを取得するには追加のクエリまたは入力操作が必要になり、応答時間が長くなる可能性があります。.
- 互換性の課題: 個別のドキュメントを個別に更新する必要があり、データの不整合が発生する可能性があります。.
- 複雑さ: 参照により、関係を管理し、データの整合性を確保するための複雑さが増します。.
例: ブログ投稿の著者名とコメント
より複雑な設定では、作成者とコメントを別々のコレクションに保存し、投稿ドキュメントで参照する場合があります。.
const authorSchema = new mongoose.Schema({
name: String,
bio: String
});
const commentSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
message: String,
date: { type: Date, default: Date.now }
});
const postSchema = new mongoose.Schema({
title: String,
content: String,
author: { type: mongoose.Schema.Types.ObjectId, ref: "Author" },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: "Comment" }]
});
const Author = mongoose.model("Author", authorSchema);
const Comment = mongoose.model("Comment", commentSchema);
const Post = mongoose.model("Post", postSchema);この設定では、PostモデルはObjectIdを使用してAuthorドキュメントとCommentドキュメントを参照します。このアプローチは、投稿とは独立してコメントや著者にアクセスしたり更新したりする必要があるアプリケーションに最適です。.
参考文献の記入
参照データを取得するには、Mongoose の fill メソッドを使用できます。.
const post = await Post.findById(postId)
.populate("author")
.populate("comments");このドキュメントは、投稿と完全な作成者およびコメントのドキュメントを取得し、投稿、作成者、およびコメントの完全なビューを提供します。.
ハイブリッドアプローチ:埋め込みと参照を組み合わせる
複雑なアプリケーションでは、特定のデータを埋め込み、他のデータを参照するハイブリッドなアプローチが必要になる場合があります。例えば、eコマースアプリケーションでは、注文に商品の詳細を埋め込みながら、顧客の詳細を参照する場合があります。.
例: 商品を埋め込み、顧客に注文を勧める
const productSchema = new mongoose.Schema({
productId: mongoose.Schema.Types.ObjectId,
name: String,
price: Number,
quantity: Number
});
const orderSchema = new mongoose.Schema({
customer: { type: mongoose.Schema.Types.ObjectId, ref: "Customer" },
products: [productSchema], // Embedding products
orderDate: { type: Date, default: Date.now }
});
const Order = mongoose.model("Order", orderSchema);この例では、
- 顧客に参照されるのは、注文数が多く、個別に問い合わせることができるためです。.
- 製品はそれぞれの特定の注文に直接関連しているため、注文内に埋め込まれます。.
このアプローチにより、頻繁にアクセスされるデータはまとめられ、より複雑な関係は個別に管理できるようになります。.
結果
Mongoose の埋め込みと参照によるリレーションシップ管理は、MongoDB で効率的なデータモデルを柔軟に設計するのに役立ちます。埋め込みは密接に関連するデータや 1 対多のリレーションシップに適していますが、参照は大規模で頻繁に更新されるリレーションシップや多対多のリレーションシップに適しています。.
それぞれのアプローチの長所と限界を理解し、データアクセスパターン、ドキュメントサイズなどの要素を考慮することで、
更新頻度を適切に設定することで、スケーラブルかつ効率的なMongoDBスキーマを設計できます。これらの戦略をMongooseアプリケーションに実装することで、関係性を効果的に管理し、堅牢で保守性の高いデータモデルを構築できます。.









