13

サイト全体でクエリを最適化しようとしています。

私は3つのモデル、写真、人物、外見を持っています

写真には多くの外観があり、外観を介して多くの人がいます

ここで、「人物」を検索して、その人物の容姿と写真を積極的に読み込みたい場合は、次のようにします。

 Person.joins(:appearances => :photo).limit(5)

さて、これが理想的かどうかはわかりませんが、仮説として、私の人物には写真に属する外観があり、写真には外観と他の人がいます。バニラSQLでこれを行うかどうか、またはどのように行うかさえわかりませんが、これが可能かどうかは知りません.

  Person.joins(:appearances => :photo => :appearaces => :person).limit(5)

この構文ではエラーが発生します。また、興味があります。ビュー内の写真の外観と人物の取得を処理しています。ロード時間を試して、これが可能かどうかを確認したかっただけです。

4

1 に答える 1

17

「積極的な読み込み」には.include、;を使用します。.joinINNERJOIN機能を実行するためのものです。あなたのケースでは、両方を使用している可能性があります(写真を取得するための参加と、追加の人を取得するためのインクルード)。これは、.join単独では積極的な読み込みを実行しないためです(したがって、後で関連付けられたエンティティにアクセスしたときにクエリが実行されます)。

ネストされたアソシエーションを積極的にロードする場合は、Ruby on Railsガイド(http://guides.rubyonrails.org/active_record_querying.html#eager-loading-multiple-associations )で概説されている構文を使用できます。

これらの線に沿った何かが機能しますか?

Photo.joins(:appearances => :person).includes(:appearances => :person).limit(5)

それとも、その人から始める必要がありますか?

Person.joins(:appearances => :photo).includes(:appearances => :photo => :appearaces => :person).limit(5)

また、最後の(小さな)メモとして、コードの最後の行に「:appearances」のスペルが間違っているため(「:appearaces」と記載されています)、問題が発生する可能性があります。

編集: いくつかのマイナーなテストの後、インクルードアソシエーションを

a => b => c => b => a

フォームが機能しません。ただし、次のフォームは行います。

a => [b => [c => [b => a]]]

もちろん、それはそれほどきれいではありませんが。

つまり、次のコードを使用します。

Person.includes(:appearances => [:photo => [:appearances => :person]]).find(38)       

次のSQLが生成されました。

Person Load (0.3ms)  SELECT `persons`.* FROM `persons` WHERE `persons`.`id` = 38 LIMIT 1
Appearance Load (0.3ms)  SELECT `appearances`.* FROM `appearances` WHERE (`appearances`.person_id = 38)
Photo Load (0.3ms)  SELECT `photos`.* FROM `photos` WHERE (`photos`.`id` = 1904)
Appearance Load (0.3ms)  SELECT `appearances`.* FROM `appearances` WHERE (`appearances`.photo_id = 1904)
Person Load (0.3ms)  SELECT `persons`.* FROM `persons` WHERE (`persons`.`id` IN (38,346))

ID#38の人物を含むすべての写真から追加の人物を積極的に読み込みます

于 2012-11-15T19:57:31.007 に答える