【问题标题】:Ordering based on another model attribute - Ruby基于另一个模型属性的排序 - Ruby
【发布时间】:2014-12-03 04:12:34
【问题描述】:

我有两个模型。类别和照片。每个类别都有很多照片。

我想对类别对象数组进行排序,使其按照片模型中的属性排序。具体来说,一张照片被下载了多少次。

我正在尝试使用类似的东西来启动实例变量

@category = Category.active.order('photos.qty_download DESC)

然后我会使用该实例变量来列出类别以及每个类别下载了多少张照片

Chicago   45
San Fran   32
Boston    23
etc

什么表达式可以在 Rails 中使用?

谢谢

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4


    【解决方案1】:

    假设您的模型如下所示:

    class Category < ActiveRecord::Base
      has_many :photos
    end
    
    class Photo < ActiveRecord::Base
      belongs_to :category
    end
    

    我们也假设:

    • 每张照片都有一个 qty_download 字段,正如您在 问题
    • 每个类别都有一个name 字段
    • 目标是根据 每个中所有照片的所有qty_download 的总和 类别
    • 可以完全排除没有相关照片的类别

    有了这些假设,你应该可以写

    Category.
      joins(:photos).
      group("categories.id, categories.name").
      select("categories.id, categories.name, sum(photos.qty_download) as total_downloads").
      order("total_downloads desc")
    

    请注意,将返回仅包含idnametotal_downloads 的“部分”类别对象。如果您需要其他类别字段,请将它们添加到 groupselect 子句中。

    更新

    较新版本的 Postgres 允许简化查询:

    Category.
      joins(:photos).
      group("categories.id").
      select("categories.*, sum(photos.qty_download) as total_downloads").
      order("total_downloads desc")
    

    请注意,在最新版本的 Postgres 中,您可以简单地按唯一 id 进行分组——您不再必须按要包含在选择中的所有属性进行分组。因此,您现在可以将类别的所有属性包含为categories.*。我将保留原始版本,因为它(略微)更有效并且与旧版本的 Postgres 向后兼容。

    【讨论】:

    • 如果您想要类别中的所有字段,请执行以下操作: select("categories.*, SUM(photos.qty_download) AS times_downloaded") 我认为简单地按“categories.id”分组应该是足够
    • 至少对于 Postgres,当您使用 group 时,select 子句中的所有内容都必须出现在 group by 子句中或者是聚合函数,因此您的任何建议都不起作用。 YMMV 与其他数据库。
    • 你确定吗?因为我在 mysql 上运行了原始版本,但现在我在使用 postgres 的 rails 项目中,并且从 rails 控制台执行以下操作非常好:Model1.limit(1).joins(:model2s).group("#{Model1.table_name}.id").select("#{Model1.table_name}.*, SUM(#{Model2.table_name}.id) AS mgids")
    • @SyedHumzaShah 我已经纠正了——我在原始回复中解决的问题已在 Postgres 的最新版本中得到修复,这是我不知道的改进。谢谢你的提示;响应已更新。
    • 有人愿意解释一下上面显示的 postgres 解决方案的每一行吗?特别是连接和组表达式
    【解决方案2】:
    Category.includes(:photos).order(qty_download: :desc).reference(:photos)
    

    【讨论】:

    • 这行不通,因为没有total_downloads 列。 (另外,您的意思可能是 references 而不是 reference。)
    • 稍微评论一下它的作用以及它的工作原理将使答案更加有用。
    猜你喜欢
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多