Docs Menu
Docs Home
/
MongoDBマニュアル
/ /

肥大化した文書

項目一覧

  • このタスクについて
  • $lookup でのコレクションの結合
  • 詳細

互いに関連しているにもかかわらずアクセスされないデータフィールドを保存すると、肥大化したドキュメントが作成され、 RAMと帯域幅の過剰な使用につながる恐れがあります。 頻繁にアクセスされるデータとインデックスで構成されるワーキングセットは、 RAM割り当てに保存されます。 ワーキングセットがRAMに収まる場合、 MongoDBはディスクからではなくメモリからクエリを実行できるため、パフォーマンスが向上します。 ただし、ドキュメントが大きすぎると、ワーキングセットがRAMに収まらない可能性があり、 MongoDBはディスクからのデータにアクセスする必要があるため、パフォーマンスが低下します。

肥大化したドキュメントを防ぐには、より小さなドキュメントでスキーマを再構築し、ドキュメント参照を使用して一緒に返されないフィールドを別々にします。 このアプローチにより、ワーキングセットのサイズが縮小され、パフォーマンスが向上します。

出版社のウェブサイトのメインページで使用される書籍情報を含む次のスキーマを考えてみましょう。 メインページには、書籍のタイトル、著者、署名メンバーのイメージのみが表示されます。 詳細を表示するには、書籍をクリックする必要があります。

{
title: "Tale of Two Cities",
author: "Charles Dickens",
genre: "Historical Fiction",
cover_image: "<url>",
year: 1859,
pages: 448,
price: 15.99,
description: "A historical novel set during the French Revolution.
}

現在のスキーマでは、ウェブサイトのメイン ページの情報を表示するには、すべての書籍情報をクエリする必要があります。 ドキュメントサイズを縮小し、クエリを効率化するには、大きなドキュメントを 2 つの小さなコレクションに分裂できます。

次の例では、書籍情報が mainBookInfoadditionalBookDetailsの 2 つのコレクションに分裂されています。

  • mainBookInfoコレクションには、ウェブサイトのメインページに表示される情報が含まれています。

  • additionalBookDetailsコレクションには、ユーザーが書籍をクリックした後に表示される追加の詳細が含まれています。

mainBookInfoコレクション:

db.mainBookInfo.insertOne(
{
_id: 1234,
title: "Tale of Two Cities",
author: "Charles Dickens",
genre: "Historical Fiction",
cover_image: "<url>"
}
)

additionalBookDetailsコレクション:

db.additionalBookDetails.insertOne(
{
title: "Tale of Two Cities",
bookId: 1234,
year: 1859,
pages: 448,
price: 15.99,
description: "A historical novel set during the French Revolution."
}
)

2 つのコレクションは、 mainBookInfoコレクションの_idフィールドとadditionalBookDetailsコレクションのbookIdフィールドによってリンクされています。 ホームページでは、必要な情報を提供するためにmainBookInfoコレクションのみが使用されます。 ユーザーが詳しく知りたい書籍を選択すると、ウェブサイトでは_idフィールドを使用してadditionalBookDetailsコレクションをクエリし、 bookIdフィールドと一致させます。

情報を 2 つのコレクションに分割することで、ドキュメントが大きくなりすぎてRAM割り当てを超えることがなくなります。

mainBookInfoコレクションとadditionalBookDetailsコレクションのデータを結合するには、アプリケーションは$lookup操作を実行する必要があります。

mainBookInfoadditionalBookDetails次の集計操作は、前の例の コレクションと コレクションを結合します。

db.mainBookInfo.aggregate( [
{
$lookup: {
from: "additionalBookDetails",
localField: "_id",
foreignField: "bookId",
as: "details"
}
},
{
$replaceRoot: {
newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$details", 0 ] }, "$$ROOT" ] }
}
},
{
$project: { details: 0 }
}
] )

この操作では、以下を返します。

[
{
_id: ObjectId('666b1235eda086b5e22dbcf1'),
title: 'Tale of Two Cities',
author: 'Charles Dickens',
genre: 'Historical Fiction',
cover_image: '<url>',
bookId: 1234,
year: 1859,
pages: 448,
price: 15.99,
description: 'A historical novel set during the French Revolution.'
}
]

この例では 、$lookup 操作は、mainBookInfo フィールドと フィールドを使用して、 コレクションとadditionalBookDetails _idbookIdコレクションを結合します。操作と$mergeObjects $replaceRootmainBookInfoadditionalBookDetails操作は、 コレクションと コレクションから結合されたドキュメントをマージします。

戻る

不要なインデックスの削除