레일에서 단일 호출로 여러 개체 저장
다음과 같은 작업을 수행하는 레일에 메서드가 있습니다.
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
문제는 더 많은 엔티티를 추가할수록 더 오래 걸립니다. 나는 이것이 모든 레코드에 대해 데이터베이스를 검색해야하기 때문이라고 생각합니다. 중첩되어 있기 때문에 부모가 구해지기 전에는 아이를 구할 수 없다는 것을 알지만, 한 번에 모든 부모를 구한 다음 모든 아이를 구하고 싶습니다. 다음과 같이하면 좋을 것입니다.
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)
그것은 단지 두 개의 데이터베이스 적중에서 모든 것을 할 것입니다. 레일에서이 작업을 쉽게 수행 할 수있는 방법이 있습니까? 아니면 한 번에 하나씩 수행해야합니까?
Foo.new 대신 Foo.create를 사용해보십시오. Create "객체 (또는 여러 객체)를 생성하고 유효성 검사가 통과하면 데이터베이스에 저장합니다. 객체가 데이터베이스에 성공적으로 저장되었는지 여부에 관계없이 결과 객체가 반환됩니다."
다음과 같이 여러 개체를 만들 수 있습니다.
# Create an Array of new objects
parents = Foo.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
그런 다음 각 상위에 대해 create를 사용하여 연결에 추가 할 수도 있습니다.
parents.each do |parent|
parent.children.create (:child_name => 'abc')
end
ActiveRecord 문서 와 Rails Guides on ActiveRecord 쿼리 인터페이스 및 ActiveRecord 연관을 모두 읽는 것이 좋습니다 . 후자는 연관을 선언 할 때 클래스가 얻는 모든 메소드에 대한 가이드를 포함합니다.
여러 삽입을 수행해야하므로 데이터베이스가 여러 번 히트합니다. 귀하의 경우 지연은 각 저장이 다른 DB 트랜잭션에서 수행되기 때문입니다. 모든 작업을 하나의 트랜잭션으로 묶어 지연 시간을 줄일 수 있습니다.
class Foo
belongs_to :parent, :class_name => "Foo"
has_many :children, :class_name => "Foo", :foreign_key=> "parent_id"
end
저장 방법은 다음과 같습니다.
# 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
save
부모 개체에 대한 호출은 자식 개체를 저장합니다.
One of the two answers found somewhere else: by Beerlington. Those two are your best bet for performance
I think your best bet performance-wise is going to be to use SQL, and bulk insert multiple rows per query. If you can build an INSERT statement that does something like:
INSERT INTO foos_bars (foo_id,bar_id) VALUES (1,1),(1,2),(1,3).... You should be able to insert thousands of rows in a single query. I didn't try your mass_habtm method, but it seems like you could to something like:
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}")
Also, if you are searching Bar by "some_attribute", make sure you have that field indexed in your database.
OR
You still might have a look at activerecord-import. It's right that it doesn't work without a model, but you could create a Model just for the import.
FooBar.import [:foo_id, :bar_id], [[1,2], [1,3]]
Cheers
You don't need a gem to hit DB fast and only once!
Jackrg has worked it out for us: https://gist.github.com/jackrg/76ade1724bd816292e4e
you need to use this gem "FastInserter" -> https://github.com/joinhandshake/fast_inserter
and inserting a large number and thousands of records is fast because this gem skips active record, and only uses a single sql raw query
참고URL : https://stackoverflow.com/questions/2509320/saving-multiple-objects-in-a-single-call-in-rails
'developer tip' 카테고리의 다른 글
jQuery UI 대화 상자에서 '제목'을 업데이트하는 방법은 무엇입니까? (0) | 2020.10.14 |
---|---|
iPhone Store Kit "iTunes Store에 연결할 수 없습니다" (0) | 2020.10.14 |
HTML에서 입력 텍스트 상자의 크기를 어떻게 정의 할 수 있습니까? (0) | 2020.10.14 |
JavaScript 날짜 개체 비교 (0) | 2020.10.14 |
R 프로그래밍 : 오일러 수는 어떻게 얻습니까? (0) | 2020.10.14 |