元の回答は、誤って読んだために関係が間違った方向に進んだため、この回答をやり直しました。
issue = {コード:"asdf-11"、タイトル:"asdf"、レポーター:{ユーザー名:"qwer"、役割:"マネージャー"}}
チケットのユーザー (作成者) に関する重要な情報を埋め込むことが賢明な決定であるかどうかは、システムの仕様によって異なります。
これらのユーザーがログインして見つけた問題を報告できるようにしていますか? もしそうなら、そのリレーションをユーザー コレクションから切り離したいかもしれません。
一方、そうでない場合は、このスキーマを簡単に回避できます。ここで私が目にする 1 つの問題は、レポーターに連絡したいのに、レポーターの職務が変更された場合、それはやや厄介なことです。ただし、これは現実世界のジレンマであり、データベースのジレンマではありません。
サブドキュメントはレポーターとの 1 対 1 の関係を表しているため、元の回答で述べた断片化の問題も発生しないはずです。
このスキーマには明らかな問題が 1 つあります。それは、繰り返しデータの変更 (正規化された形式のもの) の重複です。
例を見てみましょう。先ほどお話しした現実世界のジレンマに直面し、電話をかけられたユーザーNigel
が、自分の役割に今後の新しい職務を反映させたいと考えていると想像してください。Nigel
これは、レポーターがいるすべての行を更新し、彼role
をその新しい位置に変更する必要があることを意味します。これは、MongoDB にとって、時間のかかる、リソースを消費するクエリになる可能性があります。
繰り返しになりますが、ユーザーごとに 100 チケット (管理可能なもの) しかない場合、更新操作はそれほど悪くはなく、実際、データベースを非常に簡単に管理できます。さらに、ドキュメントの移動が (うまくいけば) ないため、これは完全に適切な更新になります。
したがって、これを埋め込む必要があるかどうかは、クエリやドキュメントなどに大きく依存しますが、このスキーマはお勧めできません。具体的には、多くのルート ドキュメント間で変更データが重複しているためです。技術的には、はい、それでうまくいく可能性がありますが、私は試しません.
代わりに、2つを分割します。
ドキュメントにオブジェクト (サブドキュメント) がある場合、1 つのクエリでそれらすべてを更新できますか?
私の元の回答の関係スタイルと同じように、はい、簡単に。
たとえば、 to の役割を更新しNigel
てMD
(前述のように)、チケットのステータスを完了に変更してみましょう。
db.tickets.update({'reporter.username':'Nigel'},{$set:{'reporter.role':'MD', status: 'completed'}})
したがって、この場合、単一のドキュメント スキーマによって CRUD が容易になります。
英語に由来する 1 つの注意点として、位置演算子を使用してルート ドキュメントの下のすべてのサブドキュメントを更新することはできません。代わりに、最初に見つかったものだけを更新します。
繰り返しますが、それが理にかなっていることを願っています。HTH
元の回答
ここに問題に関連するユーザーがいます)。別のドキュメント 'user' を作成し、'issue' ドキュメントでその ID を参照する必要がありますか (リレーショナル データベースの場合と同様)、またはすべてのユーザーのデータをサブドキュメントに残す必要がありますか?
これはかなりの質問であり、先に進む前にある程度の背景知識が必要です。
最初に考慮すべきことは、問題のサイズです。
issue = {code:"asdf-11", title:"asdf", reporter:{username:"qwer", role:"manager"}}
それほど大きくはなく、(ルート ドキュメントにある) 情報はもう必要ないので、reporter
小さくすることもできますが、問題はそれほど単純ではありません。たとえば、MongoDB JIRA を見ると: https://jira.mongodb.org/browse/SERVER-9548 (私の主張を証明するランダムなページとして) 「チケット」の内容は、実際にはかなりの量になる可能性があります。
チケットを埋め込むことで真のメリットを得る唯一の方法は、すべてのユーザー情報を、BSON ドキュメントの最大サイズである連続ストレージの単一の 16 MB ブロックに格納できる場合です (mongod
現在は によって課されています)。
すべてのチケットを 1 人のユーザーに保存することはできないと思います。
チケットをコード、タイトル、および説明に縮小したとしても、 MongoDBのドキュメントの定期的な更新と変更によって引き起こされる「スイスチーズ」の問題に苦しむ可能性があります。 .10gen.com/presentations/storage-engine-internalsは、私が言いたいことの良いリファレンスです。
通常、ユーザーがルート ユーザー ドキュメントに複数のチケットを追加すると、この問題が発生します。チケット自体も同様に変更されますが、劇的または頻繁に変更されることはありません。
もちろん、この問題は、2 の累乗のサイズ割り当てを使用して少し改善できます: http://docs.mongodb.org/manual/reference/command/collMod/#usePowerOf2Sizesは、缶に記載されているとおりに動作します。
仮説としては、チケットをサブドキュメントとしてルート ユーザーに保存するだけcode
でtitle
問題なく保存できます。
ドキュメントにオブジェクト (サブドキュメント) がある場合、1 つのクエリでそれらすべてを更新できますか?
はい、とても簡単です。これは、埋め込みによって簡単になることの 1 つです。次のようなクエリを使用できます。
db.users.update({user_id:uid,'tickets.code':'asdf-1'}, {$set:{'tickets.$.title':'Oh NOES'}})
ただし、位置演算子を使用して一度に 1 つのサブドキュメントしか更新できないことに注意してください。つまり、1 回のアトミック操作で、1 人のユーザーのすべてのチケットの日付を 5 日先に更新することはできません。
新しいチケットの追加に関しては、非常に簡単です:
db.users.update({user_id:uid},{$push:{tickets:{code:asdf-1,title:"Whoop"}}})
そうです、クエリによっては、ユーザー データ全体を 1 回の呼び出しで簡単に更新できます。
それはかなり長い答えだったので、何も見逃していないことを願っています。