ruby-on-rails - 急切加载具有多个聚合的多个关联的“Rails 方式”是什么?
问题描述
我有一个简单的 Rails 应用程序用于与这些模型的比赛:User、Team和Trip。关联是:team has_many users
和user has_many trips
。Trips 有一个distance_miles
字段。
我正在研究一个简单的视图来显示一个包含多个聚合的统计数据的团队表。
我最初的方法如下,但会导致 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)
我一直在阅读预加载和包含但似乎无法让它也获得多个聚合。下面的内容让我走到了那里,但它现在缺少 Team 中的字段,并且仍然需要其他聚合:
@teams = Team.includes(users: :trips).group(:id).sum('trips.distance_miles')
有没有我错过的“铁路方式”?
解决方案
ActiveRecord::Calculations仅在非常简单的情况下才真正有用,因为它总是创建一个单独的数据库查询.sum
。.count
您在正确的轨道上,.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,因为结果会模棱两可。相反,您需要使用窗口函数。
推荐阅读
- c# - 如何在 C# 中使用 restapi 从 github 为用户(人)获取数据?
- java - 如何根据页眉/页脚高度动态调整页边距
- r - 在闪亮的应用程序中显示变量的摘要(summary())
- android - 如何仅在 Ubuntu 上安装 Android Studio 命令行工具
- hyperlink - Select2 - 带有外部链接的选项项目中的自定义输入字段
- nativescript - NativeScript Preview 生成 QR 码,但未在应用程序内部加载
- crystal-reports - 更改名称后如何在水晶报表中打破页面?
- python-3.x - 将数据帧合并为一个
- r - 如何根据 R 中的两个分类值创建新变量?
- reactjs - 获取功能组件中select onChange的值