MongoDB
概要
どの行も同じ列を持たなければならない固定の表ではなく、カードごとに異なる項目を載せられるインデックスカードの束を思い浮かべてください。MongoDBはこのカードの束のように働きます。データを柔軟なドキュメント(ドキュメント1件をカード1枚と考えてください)として保存し、それをコレクションにまとめるドキュメントデータベースです。ドキュメントはBSONという形式で保存されますが、これはデータを名前付きの項目として書く一般的な方法である(JavaScript オブジェクト記法)を、MongoDBがバイナリ形式にしたものです。固定的なテーブルや行ではなく、各ドキュメントが独自の構造を持てるため、モデルを素早く進化させやすくなっています。データが入れ子のオブジェクトに自然にマッピングされるアプリケーションでよく選ばれます。
強み
- 柔軟なスキーマ:ドキュメントはマイグレーションなしで形を変え、進化できる。
- データがアプリケーションのオブジェクトに直接マッピングされ、変換コードが減る。
- 豊富なクエリ言語に加え、強力な集約パイプラインを備える。
- 組み込みのシャーディングによる水平スケーリングが可能。
- 入れ子フィールドや配列フィールドへの手厚いサポート。
トレードオフ
- 規律あるスキーマ設計をしないと、一貫性のないデータが容易に生まれる。
- 複数ドキュメントにまたがるトランザクションは存在するが、リレーショナルストアよりも重い。
- 結合(
$lookup)は(構造化問い合わせ言語)に比べて限定的で、データは非正規化されることが多い。 - 非正規化(参照を減らすために同じデータの複製を複数の場所に保存すること)はデータの重複を招き、更新を複雑にする。
使いどころ
コンテンツ管理、カタログ、ユーザープロフィール、イベントログ、そして正規化されたテーブルよりもドキュメントが適している、進化する階層的なデータを扱うアプリには、MongoDBを選びましょう。
バイブコーディングとの相性
AIに指示を出す際は、「スキーマレス」を「計画なし」の意味にさせないことです。明確なドキュメント構造を定義させ、必須フィールドや型を含めてJSON SchemaバリデーションやmongooseのようなODM(オブジェクト・ドキュメント・マッパー)でそれを強制させましょう。関連データを埋め込むのか、idで参照するのかを、アクセスパターンに基づいて指示し、クエリやソートに使うフィールドにはインデックスを追加させます。良いコツとして、AIにはパラメータ化されたクエリオブジェクトを使わせましょう。つまり、ユーザーが入力した生の文字列をつなぎ合わせてクエリを組み立てさせない、ということです。さらに、埋め込みと参照のどちらを選んだのか、その理由を説明させましょう。そうすれば、読み書きや更新のコストを自分で理解できます。
// スキーマバリデーションがドキュメントの一貫性を保つ
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["email", "createdAt"],
properties: {
email: { bsonType: "string" },
createdAt: { bsonType: "date" },
roles: { bsonType: "array", items: { bsonType: "string" } }
}
}
}
});
db.users.createIndex({ email: 1 }, { unique: true });
// 集約:ロールごとのアクティブユーザー数をカウント
db.users.aggregate([
{ $match: { active: true } },
{ $unwind: "$roles" },
{ $group: { _id: "$roles", count: { $sum: 1 } } }
]);