我正在尝试在整个网站中优化查询。
我有3个模特,照片,人物,外观
照片有很多出镜,很多人都是通过出场 外观表只有person_id,photo_id现在,如果我要对'人'进行搜索,我想加载他们的外观和照片,我会做这样的事情:
Person.joins(:appearances => :photo).limit(5)
现在,我不确定这是否理想,但假设我的人的外表属于照片,而照片又有外观和其他人。我甚至不知道你是否或如何在vanilla SQL中执行此操作,但我只是好奇这是否可行。
Person.joins(:appearances => :photo => :appearaces => :person).limit(5)
这种语法会导致错误,同样,我只是好奇,我正在处理我的观点中的照片的外观和人物,我只是想试验加载时间,看看是否有可能。
答案 0 :(得分:14)
对于'急切加载',您使用.include
; .join
用于执行INNER JOIN功能。对于您的情况,您可能会同时使用两者(连接来获取照片,以及包含以获得额外的人)。我提出这一点是因为单独.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))
急切地从包含身份#38
的人的所有照片中加载其他人员