Rails关联中0大小的范围作用域

3

我在弄清楚所有没有Bars的Foos的作用域方法时遇到了问题。也就是说:

class Foo < ActiveRecord::Base

  has_may :bars

end

class Bar < ActiveRecord::Base

  belongs_to :foo

end

我想编写一个作用域方法,返回所有没有 bar 的 foos。就像这样:

class Foo < ActiveRecord::Base

  has_may :bars

  scope :has_no_bars, includes(:bars).where("COUNT(foo.bars) = 0")

end

但我不理解适当的语法。有什么帮助吗?如果更容易,很高兴使用MetaWhere解决方案。


你能承受在Foo表中存储酒吧缓存计数吗?(使用计数器缓存) - Dogbert
1
嗯...那可能行,但我想知道实际查询应该是什么。 - MissingHandle
1个回答

3
你需要使用子查询或者外连接+分组+去重来解决问题。据我所知,这在Rails的AR中是不可能的。
一个近似的方法是使用AR的counter-cache功能,使你的查询变得简单。
scope :has_no_bars, where("bars_count = 0")

虽然关系不是完全正确的,但可以节省很多工作量,并且更加可扩展。


好的,在这段时间里,我找到了这篇文章:http://stackoverflow.com/questions/3676588/creating-a-named-scope-for-no-children-in-a-has-many-association它使用了子查询。你的意思是,从性能角度来看,这种方法不太好,最好使用计数器缓存? - MissingHandle
跟进 - 对于计数缓存“everything”有什么不利之处吗?或者计数缓存算作最佳实践吗? - MissingHandle
从性能角度来看,子查询始终存在风险(因为数据库无法优化查询),而计数器缓存列是免费的(只有在创建关联记录时才需要更新缓存)。但计数器缓存可能不是100%准确的(如果您没有通过Rails更新记录或跳过了回调,则可能会偏离一些数字)。 - Marcel Jackwerth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接