肥大化した文書
互いに関連しているにもかかわらずアクセスされないデータフィールドを保存すると、肥大化したドキュメントが作成され、 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 つの小さなコレクションに分裂できます。
例
次の例では、書籍情報が mainBookInfo
とadditionalBookDetails
の 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割り当てを超えることがなくなります。
$lookup でのコレクションの結合
mainBookInfo
コレクションとadditionalBookDetails
コレクションのデータを結合するには、アプリケーションは$lookup
操作を実行する必要があります。
mainBookInfo
additionalBookDetails
次の集計操作は、前の例の コレクションと コレクションを結合します。
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
_id
bookId
コレクションを結合します。操作と$mergeObjects
$replaceRoot
mainBookInfo
additionalBookDetails
操作は、 コレクションと コレクションから結合されたドキュメントをマージします。