【问题标题】:find_or_create_by using mongoid and sidekiq leads to duplicationfind_or_create_by 使用 mongoid 和 sidekiq 导致重复
【发布时间】:2014-01-01 22:22:22
【问题描述】:

Rails 4.0.2、Mongoid git alpha、sidekiq 2.17.0

使用 worker 解析 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 async 并直接在模型上执行它时,我得到了 1 个类别和两个关系产品的正确结果。

如果工作人员足够快地执行find_and_create_by,那么两个工作人员都会找到 nil 并因此创建新对象,这是有道理的。我怎样才能防止这种情况发生?

【问题讨论】:

  • 还要注意,我是从应用程序的 postgresql 版本转换而来的。 postgresql 版本正确执行了带有重复字段的异步 CSV 导入。
  • 唯一性验证在这里可以解决吗?
  • 我开始验证唯一的类别名称,但是我删除了它,因为它在第一个产品上以 category_id: nil 结尾,第二个产品是正确的
  • 将 sidekiq 限制为只有 1 个工作人员似乎可以解决问题,尽管它不太理想......
  • 我可以建议看看一些锁定 gem,例如 github.com/afeld/mongoid-lockergithub.com/burgalon/mongoid_optimistic_locking。如果您能找到解决方案,请告诉我们。

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


【解决方案1】:

唯一性验证是不够的,因为它们是由 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

【讨论】:

    【解决方案2】:

    似乎缺少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

    【讨论】:

    • 查看我对此的评论。这是我的第一个想法,但它会将第一个项目设置类别覆盖为零,第二个项目将具有正确的类别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    相关资源
    最近更新 更多