由关联计数组成的 Rails 查询,最好使用范围

Posted

技术标签:

【中文标题】由关联计数组成的 Rails 查询,最好使用范围【英文标题】:Rails queries that consist of counts on associations, preferably with scopes 【发布时间】:2013-07-02 13:25:40 【问题描述】:

我一直在为我的服务制作一个搜索页面,它包含几个基于关联的搜索参数,我可以想到一些凌乱的长 sql 混乱,但更喜欢一些更简洁的方法,作为示例,

class Person < ActiveRecord::Base
  has_many :friends
end

Friend 有一个表示友谊状态的属性,比如friend_type

class Friend < ActiveRecord::Base
  belongs_to :person
end

搜索表单将包含许多参数,其中两个用于搜索拥有超过一定数量朋友的人,以及有多少人的朋友的朋友类型设置为“bff”。

我想做的是在模型中有一些作用域方法,并且在Controller中能够做到这一点,

Person 中的一些模型范围是这样的,

scope :by_friends_count_greater_than, lambda  |value| joins(:friends).where( #count friends#, value ) if value 
scope :by_bff_count_greater_than, lambda  |value| joins(:friends).where( ##count friends with bff status## , value ) if value 

并在控制器中调用它们,

@people = Person.by_friends_count_greater_than(params[:query][:friends_count])
                 .by_bff_count_greater_than(params[:query][:bff_count])

我一直在尝试 squeel,这似乎是一个非常好的资产,考虑到它可以调用查询中的方法。是否可以以这种方式完成搜索查询?

如果有更好的方法来解决这个问题,将不胜感激。

【问题讨论】:

【参考方案1】:

您可能对 counter_cache 感兴趣以进行更简单的查询。

它会自动为每个 Person 模型增加一个计数器。

http://railscasts.com/episodes/23-counter-cache-column

你必须在你的 Person 模型中添加一个 friends_count 列

并在belongs_to上指定counter_cache

class Friend < ActiveRecord::Base
  belongs_to :person, counter_cache: true
end

【讨论】:

这是我没有想过的方法,谢谢你的建议。如果我正确理解计数器缓存,它将适用于普通朋友的计数,但它不适用于计算具有特定属性的朋友。 不,但是计数器缓存的工作方式也可以手工制作以实现高效查询。如果需要

以上是关于由关联计数组成的 Rails 查询,最好使用范围的主要内容,如果未能解决你的问题,请参考以下文章

Rails 查询关联的模型范围

RAILS:如何查询是否已有一个由一组用户组成的团队

Rails has_many 关联计数子行

mysql索引

Rails 上的两个作用域有很多通过返回比一个单一作用域更大的计数

rails 范围检查关联是不是不存在