Rails - 传递特定列以按关联模型的计数进行查询

Rails - Passing a specific column to query by count of an associated model

我有一个 rails 应用程序,模型为 "recipes"。菜谱可以被用户点赞("like" 模型)。我想要(最终)实现的是按喜欢的数量对食谱索引页面上的食谱列表进行排序。

我看过很多主题,但对我最有指导意义的两个是:

Rails 3 ActiveRecord: order and group by association count

Rails order by results count of has_many association

到目前为止,我有一个 SQL 查询,它生成食谱列表以及他们喜欢的次数:

SELECT recipes.name, COUNT(likes.id)
FROM recipes
LEFT JOIN likes on recipes.id = likes.recipe_id
GROUP BY recipes.name
ORDER BY COUNT(likes.id) DESC;

然而,当 "translating" 它变成 ActiveRecord 可以理解的东西时,我 运行 陷入了麻烦。

我得出结论,使用 Recipe.joins(:likes) 或 Recipe.left_joins(:likes) 会传递 "recipes" 中指定的所有列,这会导致以下错误:

"Column "recipes.id" 必须出现在 GROUP BY 子句中或用于聚合函数..."。

现在,因为我只需要传递 recipes.name 和 COUNT(likes.id),所以我使用了 select:

Recipe.select("recipes.name, COUNT(likes.id)").joins(:likes).group("recipes.name").order("COUNT(likes.id) DESC")

这就是我被困的地方,因为它产生了这个:

ActiveRecord::Relation [配方 id:nil,名称:"Scrambled eggz",配方 id:nil,名称:"Soup",配方 id:nil,名称:"Nutella pancakes"]

Recipe.joins("LEFT JOIN likes ON recipes.id = likes. recipe_id").group("recipes.id").order("COUNT(likes.id) ASC")

ActiveRecord 解析期望返回的结果集具有原始模型所具有的列(或列的子集)。

选择原始列的子集时,ActivereCord在将其解析时将所有其他列无效object/relation

您的查询是正确的。请注意,它使用 Recipe 模型 class,它的 Class 中不包含您的自定义字段。如果您的查询是

Recipe.select("COUNT(likes.id)").joins(:likes).group("recipes.name").order("COUNT(likes.id) DESC")

它会告诉你

ActiveRecord::Relation [Recipe id: nil, Recipe id: nil, Recipe id: nil]

但是,您仍然可以访问您的自定义字段,返回的数据保留它供您使用。你只需要给它一个名字来调用它。另外,您可以使用那个自定义字段来订购,请不要直接订购COUNT

recipes = Recipe.select("COUNT(likes.id) as total_likes").joins(:likes).group("recipes.name").order("total_likes DESC")
recipe.first.total_likes # TOTAL LIKE of first recipe

如果您想在活动记录查询中使用,这可能对您有所帮助:

Recipe.left_joins(:likes).group(:id).order("COUNT(likes.id) DESC")

针对 JOIN 的警告:

Recipe.joins(:likes).group(:id).order("COUNT(likes.id) DESC")

此查询只会return 有赞的菜谱。如果有任何菜谱没有人点赞,执行 JOINS 不会得到那些。