您可以做的是使用上面的选项二,然后将其与缓存的结果字段结合起来。您可以通过在更新中使用过滤谓词来设置数据流,以便结果字段与文档的其余部分保持一致。
第一步是向您的架构添加一个新字段,这将是您的缓存评级字段。这将允许您执行范围查询,而无需进行动态除法。你会遇到的问题是你不能原子地增加 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/