klo*_*ner 14 activerecord ruby-on-rails has-and-belongs-to-many
我有两个表,在Rails中有HABTM关系.类似于以下内容:
class Foo < ActiveRecord::Base
has_and_belongs_to_many :bars
end
class Bar < ActiveRecord::Base
has_and_belongs_to_many :foos
end
现在我有了一个新Foo对象,并希望为它预先加载数千个条形码,我预先加载了它:
@foo = Foo.create
@bars = Bar.find_all_by_some_attribute(:a)
最快的方法是什么?我试过了:
@foo.bars = @bars
@foo.bars << @bars
Run Code Online (Sandbox Code Playgroud)
两者都运行得很慢,每个条目都有以下条目bar:
bars_foos列(1.1ms)从
bars_foosSQL 显示字段(0.6ms)INSERT INTObars_foos(bar_id,foo_id)VALUES(100,117200)
我查看了ar-extensions,但是import如果没有模型(Model.import),该函数似乎无法工作,因为它不能用于连接表.
我需要编写SQL,还是Rails有更漂亮的方式?
我认为在性能方面最好的选择是使用SQL,并为每个查询批量插入多行.如果您可以构建一个类似于以下内容的INSERT语句:
INSERT INTO foos_bars (foo_id,bar_id) VALUES (1,1),(1,2),(1,3)....
Run Code Online (Sandbox Code Playgroud)
您应该能够在单个查询中插入数千行.我没有尝试你的mass_habtm方法,但似乎你可以这样:
bars = Bar.find_all_by_some_attribute(:a)
foo = Foo.create
values = bars.map {|bar| "(#{foo.id},#{bar.id})"}.join(",")
connection.execute("INSERT INTO foos_bars (foo_id, bar_id) VALUES #{values}")
Run Code Online (Sandbox Code Playgroud)
此外,如果您通过"some_attribute"搜索Bar,请确保在数据库中将该字段编入索引.
小智 7
您仍然可以查看activerecord-import.没有模型它是不行的,但你可以创建一个仅用于导入的模型.
class FooBar < ActiveRecord::Base; end
FooBar.import [:foo_id, :bar_id], [[1,2], [1,3]]
Run Code Online (Sandbox Code Playgroud)
您可以将其包装在事务中以确保HABTM完全填充,如下所示:
ActiveRecord::Base.transaction do
imported_foo = Foo.import( foo_names, foo_values )
imported_bar = Bar.import( bar_names, bar_values )
FooBar.import( [:foo_id, :bar_id], imported_foo.ids.zip(imported_bar.ids)
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3946 次 |
| 最近记录: |