Mongoid 3

时间:2015-10-08 04:27:26

标签: ruby ruby-on-rails-3 mongoid3

我希望特定模型的所有数据库交互都通过集群中的mongo主数据库,因此我将模型设置为使用强一致性。

class Photo
  include Mongoid::Document
  with consistency: :strong

  field :number, type: Integer
  # let's say a photo number is unique in the db
  validate :unique_number
end

但这似乎不起作用,因为当我将两张照片非常靠近地保存在一起时,我仍然遇到验证错误。

photo1 # db has number=1 for this object
photo1.update_attributes(number: 2)
photo2.number = 1
photo2.save! # <= this raises a validation exception

我对强烈一致性的理解是,这里不应该是一场比赛。它应该进行写入然后进行读取,因为它完全不在主要部分,所以不应该是冲突。我错过了什么?

2 个答案:

答案 0 :(得分:0)

您所遇到的区域似乎是持久性。 update_attributes正在对文档进行原子更改,看起来它没有更新持久化的photo1.Your photo2验证是从持久性内部(即在rails服务器上而不是在mongo中)触发的,并且正在查看它的记录具有。如果您在photo1.update_attributes之后运行photo1.reload,这可能会为您排序。

自从我使用mongoid 3,4以来已经有一段时间了,有一段时间它已成为主流,最近升级到5.你不会在mongoid 4中找到这种类型的问题。

如果重新加载没有帮助,请输出photo2.errors,以便我可以为您指出问题。

答案 1 :(得分:0)

事实证明,在班级调用with(consistency: :strong)只会将其应用于下一个查询。因此,在加载类时调用类方法,为第一个查询设置强一致性,  但后续查询不会触发相同的类方法,使其持久性操作与最终一致性一起运行。来自Mongoid 3.1.7 documentation

  

告诉下一个持久性[原文如此]操作存储在特定的集合,数据库或会话中。

此方法不强制执行可传入的持久性选项(如类中的其他一些方法),因此我们也可以传入consistency: :strong

Hack Fix

为了将其应用于每个*持久性操作,我将其添加到default_scope

class App
  default_scope -> { with(consistency: :strong); where({}) }
end

在这种情况下,默认范围期望返回一个Mongoid Criteria对象,因此我们在为正在进行的持久性操作设置一致性级别后返回noop where子句。

*如果开发者决定致电unscoped并剥离default_scope,则不会应用此功能。