Rails 3查询关联计数的条件

Cha*_*les 31 ruby mysql ruby-on-rails-3

在带有mysql的Rails 3中,假设我有两个模型,Customers和Purchases,显然是购买belongs_to客户.我想找到2个或更多订单的所有客户.我可以简单地说:

Customer.includes(:purchases).all.select{|c| c.purchases.count > 2}
Run Code Online (Sandbox Code Playgroud)

但实际上,上面的行会查询Customer.all和Purchase.all的大小,然后在ruby中执行"select"类型处理.在一个大型数据库中,我更愿意避免在ruby中进行所有这些"选择"计算,并让mysql进行处理,只给我合格客户列表.这要快得多(因为mysql更多地调整了这一点)并且显着减少了数据库的带宽.

不幸的是,我无法用rails中的构建块(where,having,group等)来实现代码,以实现这一点,这些内容符合(psudo-code):

Customer.joins(:purchases).where("count(purchases) > 2").all
Run Code Online (Sandbox Code Playgroud)

我将满足于直接的MySql解决方案,尽管我更喜欢在优雅的rails框架中解决这个问题.

Jam*_*msi 73

无需安装宝石即可实现此功能(尽管metawhere很酷)

Customer.joins(:purchases).group("customers.id").having("count(purchases.id) > ?",0)
Run Code Online (Sandbox Code Playgroud)


Mat*_*ner 9

关于这些东西的文档在这一点上相当稀少.如果你要做更多与此类似的查询,我会考虑使用Metawhere.使用Metawhere,你可以这样做(或类似的东西,不确定语法是否完全正确):

Customer.includes(:purchases).where(:purchases => {:count.gte => 2})
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,MetaWhere仍然使用ActiveRecord和arel来执行查询,因此它可以使用'new'trail3 3进行查询.

此外,您可能不希望.all最后调用,因为这将导致查询ping数据库.相反,您希望使用延迟加载而不是命中数据库,直到您实际需要数据(在视图中,或处理实际数据的其他方法).

  • 非常感谢.语法需要改变一点,但Metawhere只是我正在寻找的机器人.对于记录,正确的Rails代码是:`Customer.joins(:purcha).group(:customer_id).having(:customers =>(:count [:id]> 2))` (2认同)