埋め込みによるデータ整合性の強制
スキーマが複数のコレクションに同じデータを保存する場合は、関連データを埋め込むことで重複を削除できます。 更新された非正規化されたスキーマは、データ値を単一の場所に維持することで、データの一貫性を維持します。
関連データを埋め込むとスキーマが簡素化され、ユーザーが常に最新のデータを読み取るようになります。 ただし、多対多のような複雑な関係を表すには、埋め込みが最適ではない場合があります。
このタスクについて
関連データを最適に埋め込む方法は、アプリケーションによって実行されるクエリによって異なります。 単一のコレクションにデータを埋め込む場合は、パフォーマンスのあるクエリを可能にするインデックスを検討して、効率的で論理的なインデックスを可能にするようにスキーマを構築してください。
ドキュメントと参照を埋め込む利点を比較するには、「 埋め込みデータと参照の比較 」を参照してください。
始める前に
データの整合性を強制する のさまざまな方法を検討して、埋め込みがアプリケーションに最適なアプローチであることを確認します。 詳細については、「データの整合性 」を参照してください。
データベースにデータを保存する方法を更新すると、既存のインデックスとクエリに影響する可能性があります。 スキーマを更新すると、スキーマの変更を考慮してアプリケーションのインデックスとクエリも更新されます。
次の例では、eコマース アプリケーションでデータの整合性を強制します。 初期スキーマでは、製品情報は products
とsellers
コレクションに重複しています。 products
コレクションのsellerId
フィールドはsellers
コレクションへの参照であり、データをまとめてリンクします。
// products collection [ { _id: 111, sellerId: 456, name: "sweater", price: 30, rating: 4.9, color: "green" }, { _id: 222, sellerId: 456, name: "t-shirt", price: 10, rating: 4.2, color: "blue" }, { _id: 333, sellerId: 456, name: "vest", price: 20, rating: 4.7, color: "red" } ]
// sellers collection [ { _id: 456, name: "Cool Clothes Co", location: { address: "21643 Andreane Shores", state: "Ohio", country: "United States" }, phone: "567-555-0105", products: [ { id: 111, name: "sweater", price: 30 }, { id: 222, name: "t-shirt", price: 10 }, { id: 333 name: "vest", price: 20 } ] } ]
手順
スキーマを非正規化し、整合性を強制するには、製品情報をsellers
コレクション内に埋め込みます。
db.sellers.insertOne( { _id: 456, name: "Cool Clothes Co", location: { address: "21643 Andreane Shores", state: "Ohio", country: "United States" }, phone: "567-555-0105", products: [ { id: 111, name: "sweater", price: 30, rating: 4.9, color: "green" }, { id: 222, name: "t-shirt", price: 10, rating: 4.2, color: "blue" }, { id: 333, name: "vest", price: 20, rating: 4.7, color: "red" } ] } )
結果
更新されたスキーマは、ユーザーが特定の販売者をクエリすると、すべての製品情報を返します。 更新されたスキーマでは、データは単一のコレクション内で非正規化されているため、データの整合性を保つために追加のロジックやメンテナンスは必要ありません。
次のステップ
スキーマを再構成したら、一般的なクエリをサポートするためのインデックスを作成できます。 たとえば、ユーザーが色ごとの製品を頻繁にクエリする場合は、 products.color
フィールドにインデックスを作成できます。
db.sellers.createIndex( { "products.color": 1 } )