find_or_create_by使用mongoid和sidekiq导致重复

时间:2014-01-01 22:22:22

标签: ruby-on-rails-4 mongoid sidekiq

Rails 4.0.2,Mongoid git alpha,sidekiq 2.17.0

使用工作人员解析CSV文件并将内容放入mongo,但遇到了几个问题......最明显的是使用find_or_create_by时,同名产品最终会成为重复文档。

class Category
  include Mongoid::Document
  field :title, type: String

  has_many :products
end

Class Product
  include Mongoid::Document
  field :name, type: String

  belongs_to: :category
end

Class ProductWorker
  include Sidekiq::Worker

  def perform(category, name)
    category = Category.find_or_create_by( title: category )
    product = Product.find_or_create_by(name: name)
    product.category = category
    product.save
  end
end

对于同一类别中只有两个产品的CSV文件,我最终会有两个具有相同名称的类别的条目,每个产品都在不同的类别中。当我删除sidekiq异步并直接在模型上执行时,我得到了两个关系产品的1类正确结果。

如果工作人员足够快地执行find_and_create_by,那么两个工人都会找到零并因此创建新对象。我该如何防止这种情况?

2 个答案:

答案 0 :(得分:0)

看起来缺少uniqueness validation

class Category
  include Mongoid::Document
  field :title, type: String

  has_many :products

  validates_uniqueness_of :title  # Won't duplicate records
end

您还可以使用其他more accurate querying

Category.where(title: category).first_or_create!

这样,如果出现其他问题,您甚至可以rescue

答案 1 :(得分:0)

唯一性验证是不够的,因为它们是由Mongoid在模型级别定义的。

保证唯一性的唯一方法是定义unique indexes

class Category
  include Mongoid::Document
  field :title, type: String

  has_many :products

  index({ title: 1 }, background: true, unique: true)

  validates_uniqueness_of :title
end