3

私は次のようにMongoDBコレクションを持っています:

comment_id (number)
comment_title (text)
score (number)
time_score (number)
final_score (number) 
created_time (timestamp)

スコアは整数であり、通常、誰かがそのレコードに賛成または反対票を投じるたびに$inc1または-1を使用して更新されます。ただし、time_scoreは、タイムスタンプと現在の時刻、および数(1日が経過した)や数(1週間が経過した)などの他の要因に関連する関数を使用して更新されます.....など

したがって、dbで$incと$decを直接実行しますが、time_scoreの場合、dbからデータを取得して新しいスコアを計算し、書き戻します。私が心配しているのは、多くのユーザーがtime_scoreの計算中に「スコア」フィールドをインクリメントした場合、time_scoreをdbに書き込んだときに、スコアの最後の値が破損することです。

より明確にするために、Mongoでレコード内の特定のフィールドを更新すると、レコード全体が書き換えられますか、それとも更新されたフィールドのみが書き換えられますか?(これらすべてのフィールドにインデックスが付けられていると想定します)。

4

2 に答える 2

2

デフォルトでは、ドキュメント全体が書き換えられます。他に何も変更せずに変更されるフィールドを指定するには、$set演算子を使用します。

編集:この回答のコメントは正しいです-更新修飾子のいずれかにより、ドキュメント全体ではなく、関連するフィールドのみが書き換えられます。「デフォルト」とは、特別な修飾子が使用されていない場合を意味します(バニラドキュメントが提供されます)。

于 2012-11-20T22:27:40.497 に答える
0

あなたが説明しているアルゴリズムは間違いなくスレッドセーフではありません。

ドキュメント全体を読み取り、1つのフィールドを変更してからドキュメント全体を書き戻すと、競合状態が発生します。読み取り後、書き込み前に変更されたドキュメント内のフィールドは、更新によって上書きされます。

これは、おそらく古い値に基づいてドキュメント全体を更新するのではなく、$setまたは$inc演算子を使用して個々のフィールドをアトミ​​ックに設定する多くの理由の1つです。

もう1つの理由は、単一のフィールドを「インプレース」で設定/更新する方が、ドキュメント全体を書き込むよりもはるかに効率的であるということです。さらに、新しいバージョンのドキュメント全体ではなく、小さい更新ドキュメント({$ set:{field:value}})を渡す場合、ネットワークへの負荷が少なくなります。

于 2012-11-21T00:59:39.830 に答える