cap*_*aig 78 activerecord data-access ruby-on-rails
我在rails中有一个方法就是这样做:
a = Foo.new("bar")
a.save
b = Foo.new("baz")
b.save
...
x = Foo.new("123", :parent_id => a.id)
x.save
...
z = Foo.new("zxy", :parent_id => b.id)
z.save
Run Code Online (Sandbox Code Playgroud)
问题是我添加的实体越多越长.我怀疑这是因为它必须为每条记录命中数据库.由于它们是嵌套的,我知道在父母得救之前我无法拯救孩子,但我想立刻拯救所有的父母,然后是所有的孩子.做一些像这样的事情会很好:
a = Foo.new("bar")
b = Foo.new("baz")
...
saveall(a,b,...)
x = Foo.new("123", :parent_id => a.id)
...
z = Foo.new("zxy", :parent_id => b.id)
saveall(x,...,z)
Run Code Online (Sandbox Code Playgroud)
这只会在两次数据库命中时完成.有没有一种简单的方法可以在rails中执行此操作,或者我一次只执行一次?
Har*_*tty 90
由于您需要执行多次插入,因此数据库将被多次命中.您的情况延迟是因为每次保存都是在不同的数据库事务中完成的.您可以通过将所有操作包含在一个事务中来减少延迟.
class Foo
belongs_to :parent, :class_name => "Foo"
has_many :children, :class_name => "Foo", :foreign_key=> "parent_id"
end
Run Code Online (Sandbox Code Playgroud)
您的保存方法可能如下所示:
# build the parent and the children
a = Foo.new(:name => "bar")
a.children.build(:name => "123")
b = Foo.new("baz")
b.children.build(:name => "zxy")
#save parents and their children in one transaction
Foo.transaction do
a.save!
b.save!
end
Run Code Online (Sandbox Code Playgroud)
save对父对象的调用保存子对象.
Roa*_*ter 62
您可以尝试使用Foo.create而不是Foo.new.如果验证通过,则创建"创建一个对象(或多个对象)并将其保存到数据库.无论对象是否已成功保存到数据库,都会返回结果对象."
您可以创建多个这样的对象:
# Create an Array of new objects
parents = Foo.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
Run Code Online (Sandbox Code Playgroud)
然后,对于每个父级,您还可以使用create添加到其关联:
parents.each do |parent|
parent.children.create (:child_name => 'abc')
end
Run Code Online (Sandbox Code Playgroud)
我建议在ActiveRecord查询接口和ActiveRecord关联上阅读ActiveRecord文档和Rails指南.后者包含了声明关联时类获得的所有方法的指南.
Mar*_*n13 22
Rails 6引入了一个新方法insert_all,它在单个SQL INSERT语句中将多条记录插入到数据库中。
此外,此方法不会实例化任何模型,也不会调用 Active Record 回调或验证。
所以,
Foo.insert_all([
{ first_name: 'Jamie' },
{ first_name: 'Jeremy' }
])
Run Code Online (Sandbox Code Playgroud)
它的效率明显高于
Foo.create([
{ first_name: 'Jamie' },
{ first_name: 'Jeremy' }
])
Run Code Online (Sandbox Code Playgroud)
如果您只想插入新记录。
在其他地方找到了两个答案之一:由Beerlington.这两个是你表现最好的选择
我认为在性能方面最好的选择是使用SQL,并为每个查询批量插入多行.如果您可以构建一个类似于以下内容的INSERT语句:
INSERT INTO foos_bars(foo_id,bar_id)VALUES(1,1),(1,2),(1,3)....您应该能够在一个查询中插入数千行.我没有尝试你的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,请确保在数据库中将该字段编入索引.
您仍然可以查看activerecord-import.没有模型它是不行的,但你可以创建一个仅用于导入的模型.
FooBar.import [:foo_id, :bar_id], [[1,2], [1,3]]
Run Code Online (Sandbox Code Playgroud)
干杯
| 归档时间: |
|
| 查看次数: |
85922 次 |
| 最近记录: |