"Rails Way" 急于加载具有多个聚合的多个关联是什么?

What is the "Rails Way" to eager loading mutliple associations with multiple aggregations?

我有一个简单的 rails 申请与这些模型竞争:UserTeam旅行。关联是:team has_many usersuser has_many trips。行程有一个 distance_miles 字段。

我正在开发一个简单的视图来显示 table 个团队及其具有多个聚合的统计数据。

我最初的方法如下,但结果是 N+1 个查询。

@teams.each do |team|
    @team.user.joins(:trips).count()
    @team.user.joins(:trips).sum(:distance_miles)
end

以下有效,但看起来很难看,因为我最终想添加分页、排序和过滤。

@teams = Team.left_joins(users: :trips)
             .select('teams.id, teams.name, SUM(trips.distance_miles) as num_miles, COUNT(trips.id) as num_trips')
             .group(:id)

我一直在阅读 preload 和 includes,但似乎无法让它也获得多个聚合。以下内容让我走到了那里,但它现在缺少团队中的字段并且仍然需要其他聚合:

@teams = Team.includes(users: :trips).group(:id).sum('trips.distance_miles')

是否有我缺少的“rails 方式”?

提供 .sum.count 的 ActiveRecord::Calculations 只有在非常简单的情况下才真正有用,因为它总是创建一个单独的数据库查询。

您在 .select 的正确轨道上,但可以通过将代码提取到模型中来清理它:

class Team
  def self.with_trips
    trips = Trip.arel_table
    self.left_joins(users: :trips)
        .select(
          self.arel.projections, # adds the existing select clause
          trips[:distance_miles].sum.as(:num_miles),
          trips[:id].count.as(:distance_miles)
       )
       .group(:id)
  end
end

使用 .eager_load 而不是 .left_joins 将导致在 Postgres 上出现 PG::GroupingError,因为结果不明确。相反,您需要使用 window function.