3

我有一个 MongoDB 集合,如下所示:

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

分数是和整数,当有人对该记录投赞成票或反对票时,通常使用 $inc 1 或 -1 进行更新。但是 time_score 使用相对于时间戳和当前时间的函数以及其他因素进行更新,例如多少(整天过去)和多少(整周过去).....等

所以我直接在 db 上执行 $inc 和 $dec,但是对于 time_score,我从 db 中检索数据计算新分数并将其写回。我担心的是,如果许多用户在我计算 time_score 期间增加了“score”字段,那么当我将 time_score 写入 db 时,它会破坏最后一个 score 值。

更清楚地说,更新 Mongo 记录中的特定字段会重写整个记录还是只重写更新的字段?(假设所有这些字段都被索引)。

4

2 回答 2

2

默认情况下,整个文档都被重写。要指定更改的字段而不修改其他任何内容,请使用$set运算符。

编辑:对此答案的评论是正确的 - 任何更新修饰符都会导致仅重写相关字段而不是整个文档。“默认”是指不使用特殊修饰符的情况(提供了原始文档)。

于 2012-11-20T22:27:40.497 回答
0

您描述的算法绝对不是线程安全的。

当您阅读整个文档,更改一个字段然后写回整个文档时,您正在创建一个竞争条件 - 文档中在您读取之后但在您写入之前修改的任何字段都将被您的更新覆盖。

这是使用 $set 或 $inc 运算符以原子方式设置单个字段而不是根据其中可能的陈旧值更新整个文档的众多原因之一。

另一个原因是“就地”设置/更新单个字段比编写整个文档更有效。此外,当您传递较小的更新文档({$set:{field:value}},而不是文档的整个新版本)时,您的网络负载会更小。

于 2012-11-21T00:59:39.830 回答