通常、コレクションごとに複数のエンティティ タイプを格納することをお勧めします。エンティティ タイプを 1 つのドキュメント内に格納するかどうかは、もう少し検討する必要があります。
David が述べたように、データをモデル化する方法は少し主観的です。
コレクション内に複数のエンティティ タイプを格納する
最初に... 複数のエンティティをコレクションに格納する方法について話しましょう。DocumentDB コレクションはテーブルではありません。コレクションはスキーマを強制しません。つまり、異なるスキーマを持つ異なる種類のドキュメントを同じコレクションに格納できます。タイプ属性をドキュメントに追加するだけで、さまざまなタイプのエンティティを追跡できます。
コレクションは、クエリとトランザクションを実行するためのパーティションと境界の単位と考える必要があります。したがって、同じコレクション内に異なるエンティティ タイプを格納することの大きなメリットは、sprocs を介してすぐにトランザクション サポートを利用できることです。
ドキュメント内に複数のエンティティ タイプを格納する
複数のエンティティ タイプを 1 つのドキュメントに格納するかどうかは、もう少し検討が必要です。これは一般に、データの非正規化(単一のドキュメントにデータを埋め込むことによってデータ間の関係をキャプチャする) および正規化(他のドキュメントへの弱いリンクを作成することによってデータ間の関係をキャプチャする) と呼ばれます。
通常、非正規化により、読み取りパフォーマンスが向上します。
アプリケーションは、一般的な操作を完了するために発行するクエリと更新を少なくする必要がある場合があります。
通常、非正規化データ モデルは次の場合に使用します。
- エンティティ間に「<em>contains」関係がある
- エンティティ間に1 対少数の関係がある
- 非正規化されたデータは頻繁に変更されません
- 非正規化されたデータは際限なく増加しません
- 非正規化データはドキュメント内のデータに不可欠です
非正規化データ モデルの例:
{
"Id": 1001,
"Type": "Company",
"Industry": "Software",
"Employees": [
{
"Id": 10011,
"Type": "Employee",
"Name": "John Doe"
},
{
"Id": 10012,
"Type": "Employee",
"Name": "Jane Doe"
}
]
}
通常、正規化すると書き込みパフォーマンスが向上します。
非正規化よりも柔軟性が高い
クライアント側アプリケーションは、参照を解決するためにフォローアップ クエリを発行する必要があります。つまり、正規化されたデータ モデルでは、サーバーへのラウンド トリップがさらに必要になる場合があります。
一般に、正規化されたデータ モデルを使用します。
- 非正規化によりデータの重複が発生するが、重複の影響を上回るほど十分な読み取りパフォーマンスの利点が得られない場合。
- 一対多の関係を表す
- 多対多の関係を表します。
- 関連データは頻繁に変更されます
正規化されたデータ モデルの例:
{
"Id": 1001,
"Type": "Company",
"Industry": "Software"
}
{
"Id": 10011,
"Type": "Employee",
"Name": "John Doe",
"CompanyId": 1001
}
{
"Id": 10012,
"Type": "Employee",
"Name": "Jane Doe",
"CompanyId": 1001
}
ハイブリッドアプローチ
正規化と非正規化のどちらを選択するかは、白黒の選択である必要はありません。成功する設計パターンは、オブジェクトのフィールドの部分セットを正規化し、他のフィールドを非正規化することを選択できるハイブリッド アプローチであることがよくあります。
つまり、頻繁に読み取られる安定した (または不変の) プロパティを非正規化して、フォローアップ クエリの必要性を減らし、頻繁に書き込まれる/変化するフィールドを正規化して、書き込みを展開する必要性を減らすことができます。
ハイブリッド アプローチの例:
// Author documents:
[{
"id": 1,
"firstName": "Thomas",
"lastName": "Andersen",
"countOfBooks": 3,
"books": [1, 2, 3],
"images": [{
"thumbnail": "http://....png"
}, {
"profile": "http://....png"
}, {
"large": "http://....png"
}]
}, {
"id": 2,
"firstName": "William",
"lastName": "Wakefield",
"countOfBooks": 1,
"books": [1, 4, 5],
"images": [{
"thumbnail": "http://....png"
}]
}]
// Book documents:
[{
"id": 1,
"name": "DocumentDB 101",
"authors": [{
"id": 1,
"name": "Thomas Andersen",
"thumbnailUrl": "http://....png"
}, {
"id": 2,
"name": "William Wakefield",
"thumbnailUrl": "http://....png"
}]
}, {
"id": 2,
"name": "DocumentDB for RDBMS Users",
"authors": [{
"id": 1,
"name": "Thomas Andersen",
"thumbnailUrl": "http://....png"
}, ]
}]