简体   繁体   English

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

[英]Rails query for record and latest association record efficiently with includes?

I'm having trouble with a rails activerecord query. 我在使用rails activerecord查询时遇到问题。

I have 2 tables. 我有2张桌子。

One for Projects: 一个项目:

id | name | created_at | updated_at

One for Project Reports: 一个用于项目报告:

id | project_id | number | created_at | updated_at

The corresponding class for Project: Project的相应类:

class Project < ActiveRecord::Base
  has_many :project_reports

  def latest_report_number
    project_reports.last.number
  end
end

And ProjectReports: 和ProjectReports:

class ProjectReport < ActiveRecord::Base
  belongs_to :project
end

I'm attempting to write a query to get a list of the projects and the most recent report for the project. 我正在尝试编写查询以获取项目列表和该项目的最新报告。

I can do this in the following way, but this leads to a N+1 situation: 我可以通过以下方式执行此操作,但这会导致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}" }

I therefor wanted to use rails 'includes' feature so that I don't run into the N+1 situation: 因此,我想使用rails的“ includes”功能,以免遇到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}" }

This causes my query to no longer work: 这导致我的查询不再起作用:

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

How can I write my query so that I both accomplish the goal and limit the number of times I hit the database (ideally with includes)? 如何编写查询,以便既完成目标又限制我访问数据库的次数(理想情况下是包含)?

In the case of a join query, includes asks for extra columns from the associated table (ie tasks ) in order to build the associated objects without an additional query. 在联接查询的情况下, includes要求从关联的表中获取额外的列(即tasks ),以便在没有附加查询的情况下构建关联的对象。 Normally, that's a welcome optimization, but in the case of a GROUP BY clause, you wind up with an invalid SELECT . 通常,这是一个受欢迎的优化,但是在使用GROUP BY子句的情况下,您将获得无效的SELECT

In your case, you want a completely separate query to load the associations, so preload is a better choice. 在您的情况下,您希望使用完全独立的查询来加载关联,因此preload是一个更好的选择。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM