13

我正在尝试优化我整个网站的查询。

我有 3 个模型,照片,人物,外观

照片有_many外观,而很多人通过appearances表只有一个person_id,photo_id

现在,如果我要搜索“人”并且我想急切地加载他们的外表和照片,我会做这样的事情:

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

现在,我不确定这是否理想,但假设我的人具有属于照片的外观,而照片又具有外观和其他人。我什至不知道您是否或如何在 vanilla SQL 中执行此操作,但我只是好奇这是否可能。

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

这种语法再次导致错误,我只是好奇,我正在处理在我的视图中获取照片的外观和人物,我只是想尝试加载时间,看看这是否可能。

4

1 回答 1

17

对于“急切加载”,您使用.include; .join用于执行 INNER JOIN 功能。对于您的情况,您似乎可能会同时使用两者(加入获取照片,包含获取更多人)。我提出这一点是因为.join单独不会执行急切加载(因此它会在访问关联实体时进行查询)。

如果您希望预先加载嵌套关联,可以使用http://guides.rubyonrails.org/active_record_querying.html#eager-loading-multiple-associations上的 Ruby on Rails 指南中概述的语法

这些方面的东西会起作用吗?

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 回答