1

我有 mongodb 集合users。每个用户都有一个rating介于 1 到 5 之间的字段。这意味着当用户对另一个用户投票时,他“给”他的投票是 1 到 5 之间的数字。我在将这些数据存储在 mongo 文档中时遇到了问题,因为我必须按rating字段查询用户集合,我必须以原子方式更新它......

  1. 如果我可以votes_number使用$inc操作员更新但我不能原子设置时同时存储评分和投票数rating = ((rating*votes) + vote_val)/(votes+1)

  2. 我可以在文档中保留票数和票数并使用两者进行更新,$inc但是我不能像WHERE votes_sum/votes_num > 3...一样查询

这个问题有什么解决办法吗?

4

1 回答 1

2

您可以做的是使用上面的选项二,然后将其与缓存的结果字段结合起来。您可以通过在更新中使用过滤谓词来设置数据流,以便结果字段与文档的其余部分保持一致。

第一步是向您的架构添加一个新字段,这将是您的缓存评级字段。这将允许您执行范围查询,而无需进行动态除法。你会遇到的问题是你不能原子地增加 votes_sum 和 votes_num 字段并且在同一个原子操作中设置缓存的评分字段。所以这就是你要做的。

1) 自动增加 votes_sum 和 votes_num 字段
2) 获取更新文档的 _id、 votes_sum 和 votes_num
3) 更新评级,但作为过滤谓词的一部分,包括 _id、预期 votes_sum 和预期 votes_num 字段。

db.collection.update({_id: $id, votes_sum: $votes_sum, votes_num: $votes_num}, {$set: {rating: $votes_sum / $votes_num}});

这将确保自您更新文档以来没有任何变化。如果其他人出现并在您更新它们和生成评级之间更新这些字段,则该文档将不会在更新语句的查找部分中返回,因此不会使用陈旧数据进行更新

这种模式利用了在 MongoDB 中的文档级别写入是原子的这一事实,因此您不必担心文档中数据的一致性。好消息是评分将被正确设置,因为每次更新 votes_sum 和 votes_num 字段的操作之后都会更新评分。

有关一些示例代码,请参见此处:http: //docs.mongodb.org/manual/tutorial/isolate-sequence-of-operations/

于 2013-08-26T18:29:15.330 回答