Rails有效地查询记录和最新的关联记录吗?

时间:2015-09-21 01:20:49

标签: ruby-on-rails ruby activerecord

我在使用rails activerecord查询时遇到问题。

我有2张桌子。

一个项目:

id | name | created_at | updated_at

项目报告之一:

id | project_id | number | created_at | updated_at

Project的相应类:

class Project < ActiveRecord::Base
  has_many :project_reports

  def latest_report_number
    project_reports.last.number
  end
end

和ProjectReports:

class ProjectReport < ActiveRecord::Base
  belongs_to :project
end

我正在尝试编写查询以获取项目列表和项目的最新报告。

我可以通过以下方式执行此操作,但这会导致N + 1情况:

Project
  .select("projects.*, max(project_reports.created_at) as latest_report")
  .joins(:project_reports)
  .order("latest_report desc")
  .group("projects.id")
  .map { |p| "#{p.name}: #{p.latest_report_number}" }

我因此想使用rails'include'功能,这样我就不会遇到N + 1的情况:

Project
  .select("projects.*, max(project_reports.created_at) as latest_report")
  .joins(:project_reports)
  .order("latest_report desc")
  .group("projects.id")
  .includes(:project_reports)    # <----
  .map { |p| "#{p.name}: #{p.latest_report_number}" }

这导致我的查询不再有效:

PG::GroupingError: ERROR:  column "project_reports.id" must appear in 
the GROUP BY clause or be used in an aggregate function

我如何编写查询以便完成目标并限制我点击数据库的次数(理想情况下是包含)?

1 个答案:

答案 0 :(得分:1)

在连接查询的情况下,setState要求关联表中的额外列(即includes),以便在没有其他查询的情况下构建关联的对象。通常情况下,这是一个受欢迎的优化,但对于tasks条款,最终会出现无效GROUP BY

在您的情况下,您需要一个完全独立的查询来加载关联,因此SELECT是更好的选择。

preload