元のスキーマのコンテキストで、最初に 2 番目の質問に対処します。ユーザー名をインデックスとして使用すると、可変フィールド名を使用するため、クエリがはるかに難しくなります。同様に、ユーザー オブジェクト内のそのようなフィールドにインデックスを付けると、個別のフィールド パスごとに独自のインデックスが必要になるため、スケーリングされません。とはいえ、非効率的なクエリでも可能です。
db.companies.drop()
db.companies.insert({
_id: "wuduwudu",
users: [
{ pkanane: { fullName: "Papa Kwame" } }
]
});
db.companies.find({ "users.pkanane": { $exists: true }}, { "users.pkanane.fullName": 1 });
{ "_id" : "wuduwudu", "users" : [ { "pkanane" : { "fullName" : "Papa Kwame" } } ] }
改善はusers
、埋め込まれたユーザー オブジェクトの配列を作成することです。このスキーマを使用すると、フィールドでマルチキー インデックスusers.username
を利用でき、Mongo は各ドキュメントの配列内のすべてのユーザー名にインデックスを付けます。
db.companies.drop()
db.companies.insert({
_id: "westpalm",
users: [
{ username: "pkanane", fullName: "Papa Kwame" }
]
});
db.companies.find({ "users.username": "pkanane" }, { "users.pkanane.fullName": 1 });
{ "_id" : "wuduwudu", "users" : [ { "pkanane" : { "fullName" : "Papa Kwame" } } ] });
スキーマを再考するには、会社とユーザー オブジェクトの構造を調べることから始めます。上で述べたように、動的フィールド名は索引付けではうまく機能しません。会社名をドキュメントの唯一の最上位キーとして使用しないことをお勧めします。上記の例のように に使用するか、MongoDB に依存して ObjectId を生成し、会社名を、 など_id
と一緒に独自のフィールドに保存できます。users
customers
一般に、ユーザーはほとんどのアプリケーションで最上級のオブジェクトです。会社のコンテキスト外でそれらを使用および編集する場合は、それらを独自のコレクションに保存し、代わりに会社のドキュメントにユーザー ID の配列を保持することを検討します。また、あなた自身の例では、両社間で「pkanane」を複製していました。これは、独自のコレクション内のユーザー ドキュメントを参照する方がよいかもしれないという別の匂いです。顧客、車両、および設定は、アプリケーションで最上級のオブジェクトではない可能性があるため、それらを埋め込む方が適切な場合があります。MongoDB ドキュメントのスキーマ設計のエントリは、出発点として適しています (ベスト プラクティスのリストにリンクしています)。
埋め込みドキュメントに関するもう 1 つの課題は、アプリケーションで 1 つの埋め込みドキュメントを単独で編集できるようにする必要があることです。これは、アドレス帳をユーザー ドキュメントに埋め込み、"住所の編集" フォームを提供するスキーマでは一般的です。変更可能なオブジェクトの配列位置を使用することは、オブジェクトに不変フィールドがあるため信頼できません。上記の 2 番目のコード例のスキーマを使用するusername
と、それが不変である場合に使用できます。または、埋め込みドキュメントごとに一意の ObjectId を保存し、それを参照することもできます。
最後に、ユーザーを自分のコレクションに移動することになるかもしれませんが、このアドバイスは、会社に埋め込んだままにしておくものすべてに有効です。