基于列的平均值进行过滤的Rails范围

时间:2018-08-07 15:25:26

标签: ruby-on-rails activerecord

因此,我有一个餐厅模型,一个餐厅有很多评论,每个评论的评分都为1-5。我有一个功能,允许用户按最低评分过滤餐馆列表,但是目前,它在过滤之前将所有餐馆都抢了下来,然后使用Ruby select语句消除了我不想要的餐馆。我想将其切换到一个更干净的解决方案,该解决方案可以让SQL进行过滤,但是在弄清楚如何使用范围进行处理时遇到了困难。

我已经知道了,但这给了我一个“滥用聚合函数AVG()”的错误:

scope :min_rating, -> (rating) { joins(:reviews).where('AVG(reviews.rating) > ?', rating)  if rating}

此范围的正确语法是什么?

1 个答案:

答案 0 :(得分:2)

计算平均值时,您需要.group("restaurants.id")或类似的内容告诉它要整理哪些评论集,然后将其移至.having条件(在该分组之后应用):< / p>

scope :min_rating, -> (rating) { joins(:reviews).group("restaurants.id").having('AVG(reviews.rating) > ?', rating) if rating }

但是,这是一个很好的例子,说明了对数据进行非规范化可能是合理的-在average_rating上添加restaurants列,并在每次保存评论时重新计算。与分组计算不同,该列可以建立索引并进行有效过滤-以存储评论为代价;这是一个权衡。