在activerecord中深度嵌套的连接

时间:2012-11-15 19:38:50

标签: activerecord

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

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

照片有很多出镜,很多人都是通过出场 外观表只有person_id,photo_id

现在,如果我要对'人'进行搜索,我想加载他们的外观和照片,我会做这样的事情:

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

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

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

这种语法会导致错误,同样,我只是好奇,我正在处理我的观点中的照片的外观和人物,我只是想试验加载时间,看看是否有可能。

1 个答案:

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

的人的所有照片中加载其他人员