マングースの個体数について最初に理解することは、それが魔法ではなく、自分ですべてを行うことなく関連情報を取得できる便利な方法であるということです。
この概念は基本的に、データを埋め込むのではなく、別のコレクションにデータを配置する必要があると判断した場合に使用します。主な考慮事項は、通常、ドキュメントサイズ、または関連情報が頻繁に更新される可能性がある場合です。埋め込まれたデータを扱いにくい状態に維持します。
「魔法ではない」部分は、本質的に、別のソースを「参照」するときに、populate関数が、親の結果を「マージ」するために、その「関連する」コレクションに追加のクエリを作成することです。取得したオブジェクト。これは自分で行うこともできますが、タスクを簡略化するための便利な方法があります。明らかな「パフォーマンス」の考慮事項は、すべての情報を取得するためにデータベース(MongoDBインスタンス)への単一のラウンドトリップがないことです。常に複数あります。
サンプルとして、2つのコレクションを取ります:
{
"_id": ObjectId("5392fea00ff066b7d533a765"),
"customerName": "Bill",
"items": [
ObjectId("5392fee10ff066b7d533a766"),
ObjectId("5392fefe0ff066b7d533a767")
]
}
そしてアイテム:
{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 }
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
「参照」モデルまたは(内部での)populateの使用によって実行できる「最良の」方法は次のとおりです。
var order = db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
order.items = db.items.find({ "_id": { "$in": order.items } ).toArray();
したがって、そのデータを「結合」するために、明らかに「少なくとも」2つのクエリと操作があります。
埋め込みの概念は、本質的に、「結合」をサポートしないことに対処する方法に対するMongoDBの答えです。そのため、データを正規化されたコレクションに分割するのではなく、それを使用するドキュメント内に「関連する」データを直接埋め込もうとします。ここでの利点は、「関連する」情報を取得するための単一の「読み取り」操作と、「親」エントリと「子」エントリの両方を更新するための単一の「書き込み」操作があることです。クライアントで「リスト」を処理したり、「複数の」書き込み操作を受け入れたりせずに、できれば「バッチ」処理で、一度に「多くの」子。
その場合、データはかなり次のようになります(上記の例と比較して):
{
"_id": ObjectId("5392fea00ff066b7d533a765"),
"customerName": "Bill",
"items": [
{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 },
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
]
}
したがって、実際にデータを取得するのは次の問題です。
db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
どちらの長所と短所も、常にアプリケーションの使用パターンに大きく依存します。しかし一目で:
埋め込み
-
データが埋め込まれたドキュメントの合計サイズは、通常、16 MBのストレージ(BSONの制限)を超えないか、(ガイドラインとして)500以上のエントリを含むアレイがあります。
-
埋め込まれているデータは、通常、頻繁に変更する必要はありません。したがって、変更を呼び出すためだけに、多くの親ドキュメント間で同じ情報でそれらの「複製」を更新する必要がない、非正規化に起因する「複製」で生きることができます。
-
関連データは、親に関連して頻繁に使用されます。つまり、「読み取り/書き込み」の場合、ほとんどの場合、親と子の両方に対して「読み取り/書き込み」が必要な場合は、不可分操作のためにデータを埋め込むのが理にかなっています。
参照
-
関連データは常に16MBのBSON制限を超えます。 「バケット化」のハイブリッドアプローチをいつでも検討できますが、メインドキュメントの一般的なハード制限に違反することはできません。一般的なケースは、「コメント」アクティビティが非常に大きいと予想される「投稿」と「コメント」です。
-
関連データは定期的に更新する必要があります。または、基本的に、そのデータが多くの親の間で「共有」され、「関連する」データが頻繁に変更されるために「正規化」する場合、その「子」アイテムが発生するすべての「親」の埋め込みアイテムを更新することは実用的ではありません。 。より簡単なケースは、「子」を参照して一度変更することです。
-
読み取りと書き込みは明確に分離されています。 「親」を読み取るときに「関連する」情報を常に必要としない場合や、子に書き込むときに常に「親」を変更する必要がない場合は、モデルを分離するのに十分な理由があります。参照されているように。さらに、多くの「サブドキュメント」を一度に更新したいという一般的な要望があり、それらの「サブドキュメント」が実際には別のコレクションへの参照である場合、データが別の場所にある場合、実装の方が効率的であることがよくあります。コレクション。
そのため、実際には、データモデリングに関するMongoDBドキュメントのどちらの位置についても、「賛否両論」についてはるかに幅広い議論があります。これは、populateメソッドでサポートされている埋め込みモデルまたは参照モデルを使用してアプローチするさまざまなユースケースと方法をカバーしています。
「ドットポイント」が役立つことを願っていますが、一般的には、アプリケーションのデータ使用パターンを検討し、最適なものを選択することをお勧めします。 MongoDBを選択した理由は、「すべき」を埋め込む「オプション」があることですが、実際には、アプリケーションが「データを使用する」方法によって、どのメソッドがデータモデリングのどの部分に適しているかが決定されます(そうではないため)。 「オールオアナッシング」)最高。
- これは元々書かれていたので、MongoDBは
$lookup
を導入したことに注意してください。 サーバー上のコレクション間で実際に「結合」を実行する演算子。ここでの一般的な説明の目的で、ほとんどの状況で、populate()
によって発生する「複数のクエリ」のオーバーヘッドよりも「優れた」ホイストを使用します。 また、一般的に「複数のクエリ」には、「かなりのオーバーヘッド」があります。$lookup
で発生した 操作。コアデザインの原則は、「どこかからフェッチする」のではなく、「すでにそこにある」という意味です。基本的に、「ポケットの中」と「棚の上」の違いであり、I / O用語では、通常、「ダウンタウンの図書館の棚の上」のようになります。 、特にネットワークベースのリクエストの場合はさらに遠くにあります。