我有mongodb collection users
。
每个用户都有一个名为rating
的字段,介于1和5之间。这意味着当用户对另一个用户进行投票时,他'给'他的投票是1到5之间的数字。我在存储这些数据时遇到问题在mongo文档中因为我必须通过rating
字段查询用户集合,我必须以原子方式更新它...
如果我可以使用votes_number
运算符更新$inc
但我无法存储评分和投票数,但我无法原子设置rating = ((rating*votes) + vote_val)/(votes+1)
我可以在文档中保留投票数和投票数,并使用$inc
进行更新,但后来我无法查询WHERE votes_sum/votes_num > 3
...
这个问题有解决办法吗?
答案 0 :(得分:2)
您可以使用上面的选项二,然后将其与缓存的结果字段组合。您可以设置数据流,以便在更新时使用过滤谓词使结果字段与文档的其余部分保持一致。
第一步是在您的架构中添加一个新字段,该字段将是您的缓存评级字段。这将允许您执行范围查询,而无需进行动态划分。你遇到的问题是你无法原子地增加votes_sum& votes_num fields AND在相同的原子操作中设置缓存的评级字段。所以这就是你做的。
1)以原子方式递增votes_sum和voting_num字段
2)抓住_id,votes_sum& vote_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/