过滤父母的孩子属性,但渴望

这个标题有点愚蠢,所以这里是一个例子。 假设我们有一个带有模型ShipPirateParrot的Rails 3应用程序。 一艘船拥有多个海盗,一个海盗拥有多个鹦鹉。

Ship.includes(pirates: :parrots).where('parrots.name LIKE ?', '%polly%')

这将返回船舶至少有一个海盗与至少一个鹦鹉的名字是像“polly”。 我也希望它能够为这些船只急切地装载所有的海盗和鹦鹉 ......但实际上只有与鹦鹉匹配的海盗才会急于装载,其中只有匹配的鹦鹉才会急于装载。 生成的SQL如下所示:

SELECT ships.id AS t0_r0, ships.name AS t0_r1, pirates.id AS t1_r0, pirates.name AS t1_r1, parrots.id AS t2_r0, parrots.name AS t2_r1 FROM ships LEFT OUTER JOIN pirates ON pirates.ship_id = ships.id LEFT OUTER JOIN parrots ON parrots.pirate_id = pirates.id WHERE (parrots.name LIKE '%polly%')

在没有条件的情况下执行Ship.includes(pirates: :parrots) ,ActiveRecord会生成一些更接近我想要的查询:

SELECT ships.* FROM ships
SELECT pirates.* FROM pirates WHERE pirates.ship_id IN (ship IDs from previous query)
SELECT parrots.* FROM parrots WHERE parrots.pirate_id IN (pirate IDs from previous query)

如果我能以某种方式更改第一个查询以使用第一个示例中的SQL,那么它将完成我想要的操作:

SELECT ships.* FROM ships LEFT OUTER JOIN pirates ON pirates.ship_id = ships.id LEFT OUTER JOIN parrots ON parrots.pirate_id = pirates.id WHERE (parrots.name LIKE '%polly%')
SELECT pirates.* FROM pirates WHERE pirates.ship_id IN (ship IDs from previous query)
SELECT parrots.* FROM parrots WHERE parrots.pirate_id IN (pirate IDs from previous query)

但我不知道有什么办法让ActiveRecord执行此操作,或者有任何方法可以自己完成,并“手动”连接热切加载(在我的情况下这是避免N + 1查询爆炸所必需的)。 任何想法或建议,将不胜感激。


Ship.joins(pirates: :parrots).where('parrots.name LIKE ?', '%polly%').preload(pirates: :parrots)

需要导轨3+


如果INNER JOIN是你想要的,我想

Ship.includes(pirates: :parrots).where('parrots.name LIKE ?', '%polly%').joins(pirates: :parrots)

完成它。

链接地址: http://www.djcxy.com/p/39533.html

上一篇: Filter parents by child attribute, but eager

下一篇: Include another HTML file in a HTML file