【发布时间】:2013-05-16 14:56:19
【问题描述】:
我有:
class Foo
include Mongoid::Document
field :year, :type => Integer, :default => Time.now.utc.year
field :month, :type => Integer, :default => Time.now.utc.month
field :day, :type => Integer, :default => Time.now.utc.day
validates :day, :uniqueness => { :scope => [:month,:year] }
end
我做了以下两次:
Foo.create(:day => 24, :year => 2013, :month => 5)
我没有收到验证错误。相反,我有两条相同的记录。我做错了什么?
【问题讨论】:
-
这两个创建执行的速度有多快,如果它们被立即触发,这里就有一个继承竞争条件。也许初始写入在第二次创建验证之前被缓存。我的建议是直接在 mongodb 中设置一个多键唯一约束。
db.foos.ensureIndex( { "day": 1, "year": 1, "month": 1 }, { unique: true } ) -
不是马上。我可以等待 30 秒甚至几分钟,我仍然会得到重复的记录。任何地方都没有比赛条件。作为最后的手段,我可以直接在 Mongodb 中考虑唯一约束。但是,我希望通过 Mongoid(应用层)找到一种方法。
-
在生产中你应该两者都做,如果遇到多个并发插入,可能会遇到上述竞争条件。至于手头的问题,我认为语法或逻辑上没有任何错误。可能的问题:
Mongoid behaves slightly different to Active Record when using #valid? on already persisted data. Active Record's #valid? will run all validations whereas Mongoid's #valid? will only run validations on documents that are in memory as an optimization.mongoid.org/en/mongoid/docs/validation.html -
对于这种情况,插入在单个线程上运行(通过工作者/cron 作业)。不是同时的。怀疑这里会发生竞争条件
-
来自mongoid.org/en/mongoid/docs/validation.html,对于 validates_uniqueness_of :name ... validates :name, uniqueness: true ... 验证属性是否唯一。请注意,对于嵌入式文档,这只会检查该字段在父文档的上下文中是否唯一,而不是在整个数据库中。