0

我想做与此问题如何编写 Rake 任务以将数据导入 Rails 应用程序中解释的相同的事情?.

但是,我对接受的答案不满意,因为它不考虑源中已删除的项目。

考虑到源中已删除的条目,最简单、最符合标准的方法是什么?

笔记:

  • 当使用 .find_or_initialize_by_identifier 并且从不删除时,多余的条目会保留在表中。
  • 据我所知,在每次导入之前使用 .delete_all 时,主键不会重置并迅速接近其限制。
  • 我可以删除表并在 rake 任务中使用 ::Migrations.create_table 但是架构和迁移中的定义必须与 rake 任务中的代码保持同步,这似乎是不可取的。
4

2 回答 2

0

我使用的是.delete_all 和一个没有rails 默认idauto_increment 列的表模式,以避免在.delete_all 之后增加值。

create_table :airport_locations, id: false do |t|
  t.string :iata_faa_code, :primary_key
  t.float :latitude
  t.float :longitude
end
add_index :airport_locations, :iata_faa_code

笔记

  • 数据集相当小(约 5000 个条目)并且更新很少发生。
  • 如果表格很小,跟踪 Max Williams 回答中解释的已删除项目是可行的。尽管具有数千个条目的表可能需要大量内存,并且可能需要更复杂的策略(例如使用临时表)来查找已删除的条目。
于 2015-04-22T19:53:25.223 回答
0

您绝对不应该删除所有记录,然后从数据中重新创建它们。这将产生各种问题,例如破坏其他表中的任何外键字段,这些字段在删除之前指向对象。这就像为了拥有一扇不同颜色的门而将一所房子推倒并重建它。因此,“查看它是否存在,如果存在则更新它(如果它不同),如果不存在则创建它”是正确的使用策略。

你没有说你的删除标准是什么,但如果它是“应该删除导入数据中未提及的任何记录”,那么你只需要跟踪输入数据中的一些唯一字段,然后删除其唯一字段不在该列表中的所有记录。

因此,您进行导入的代码可能看起来像这样(从另一个问题复制代码:此代码以非常笨拙的方式设置数据,但我不打算在这里解决)

namespace :data do
  desc "import data from files to database"
  task :import => :environment do
    file = File.open(<file to import>)
    identifiers = []
    file.each do |line|
      #disclaimer: this way of setting the data from attrs[0], attrs[1] etc is crappy and fragile and is not how i would do it
      attrs = line.split(":")
      identifier = attrs[0]
      identifiers << identifier
      if p = Product.find_or_initialize_by_identifier(identifier)
        p.name = attrs[1]
        etc...
        p.save!
      end
    end
    #destroy any which didn't appear in the import data
    Product.where("identifier not in (?)", identifiers).each(&:destroy)
  end
end
于 2015-04-10T09:26:34.540 回答