我想插入数以百万计的数据,没有一个选项来击中数据库的许多次,而不是使用这个gem做批量插入,但正如它所说,它只是做批量插入,没有内存中的Activerecord对象,它不能运行之前和之后保存回调。
所以,为了做到这一点,我写了一个代码来手动触发before_callback。
valid_books = []
invalid_books = []
books.each do |book|
if book.valid?
valid_books << book
else
invalid_books << book
end
end
valid_books.each do |book|
book.run_callbacks(:save) { false }
book.run_callbacks(:create) { false }
end
Book.import valid_books, validate: false
引用自gem文档本身。现在,在导入数据后,如何在回调后运行。谢谢你!
当我们有before
和after
回调时,bulk_import
是没有用的。
您将不得不为每个插入的记录调用after_callback,或者使用.create
,它将接受批量数据。
Ex: Model.create({{...}, {...}, {...} ...})
我建议你在后台作业中创建记录:
Job1
- 为
batch_import
设置ActiveJob
- 将数据解析为JSON。Ex -
data_hash: {{...}, {...}, {...} ...}
- 批量拆分数据并循环通过每个批次 呼叫
Job2(batch_data)
Job2
- 为
batch_create
设置ActiveJob
- 有
DB.Transaction
块 - Do
Model.create(batch_data)
- 在
begin..rescue..ensure
块内包装以上步骤
与:
- 你会有
validations
&callbacks
按预期调用 - 让多个worker在后台完成创建记录的任务
- 你可以在
rescue block
中设置异常跟踪器来通知错误
建议:
- 如果您正在使用
Postgres
DB,那么我建议使用Que
。 - 广泛使用的队列是
resque
,Redis
支持 - 异常管理和 Errbit
- 跟踪异常的气闸
如果你使用的是Postgres,你可以在回调后的导入步骤中添加这个:
Book.import valid_books, validate: false
valid_books.each do |book|
book.run_callbacks(:save) { true }
book.run_callbacks(:create) { true }
end