简体   繁体   English

Rails 4+,按孩子排序父记录列表

[英]Rails 4+, ordering list of parent records by children

I have a page that displays a lot of data and I'm working on optimizing it and I'm struggling with balancing reducing DB queries with getting the proper data in the order I need. 我有一个页面显示大量数据,并且我正在努力对其进行优化,并且我在平衡减少数据库查询与按需要的顺序获取适当的数据方面做出了努力。

A Transaction is the top-level element, and each transaction has multiple workflows and each workflow has many milestones . Transaction是顶级元素,每个transaction都有多个workflows ,每个workflow都有许多milestones I order the workflows and milestones by a position:integer attribute. 我通过position:integer属性对workflowsmilestones进行排序。

# Top-level element
class Transaction < ApplicationRecord
  has_many :workflows
  has_many :team_members
end

# Parent element for milestones
class Workflow < ApplicationRecord
  belongs_to :transaction
  has_many :milestones
end

# Unique individual
class Person < ApplicationRecord
  has_many :team_members
end

# Acts as a join between Transactions and Persons
class TeamMember < ApplicationRecord
  belongs_to :transaction
  belongs_to :person
  belongs_to :team_member_type
end

class TeamMemberType < ApplicationRecord
  has_many :team_members
end

In my controller this is what I have: 在我的控制器中,这就是我所拥有的:

def show
  @transaction = Transaction.includes(
    team_members: [:person, :team_member_type],
    workflows: [:milestones]
  ).find(params[id])
end

This gathers all the data I need in 1 DB query, but the problem is when I iterate over the milestones for a workflow, I need it to be sorted by the position attribute. 这收集了我在1个DB查询中需要的所有数据,但是问题是,当我遍历工作流的里程碑时,我需要将其按position属性进行排序。

I can grab the data from the DB and then sort it with Ruby, but that seems inefficient and I would prefer to get it all done in the DB properly (if possible). 我可以从数据库中获取数据,然后使用Ruby对其进行排序,但这似乎效率不高,我宁愿将所有数据正确地在数据库中完成(如果可能的话)。

If I were to write it with an N+1 issue, it would look like this: 如果要编写N+1问题,它将看起来像这样:

<% @workflows.order(:position).each do |workflow| %>
  <%= workflow.name %>
  <% workflow.milestones.order(:position).each do |milestone| %>
    <%= milestone.name %>
  <% end %>
<% end %>

I think everyone agrees that's a bad idea, but I'm struggling to figure out how to sort the data and optimize my DB calls at the same time. 我认为每个人都同意这是一个坏主意,但我一直在努力寻找如何对数据进行排序并同时优化数据库调用的方法。

I also sort the team_members by the team_member_type.value attribute, but that's the same question as above. 我还根据team_member_type.value属性对team_members进行了排序,但这与上面的问题相同。

<% @team_members.includes(:team_member_type, :person).order("team_member_types.value").each do |team_member| %>
  ...
<% end %>

My main objective is efficiency. 我的主要目标是效率。 If I need to use some Query objects to clean it up and raw SQL, I'm ok with that, I'm just not extremely proficient at SQL and would prefer using ActiveRecord if reasonable. 如果我需要使用一些Query对象来清理它和原始SQL,我也可以,我只是不太精通SQL,因此在合理的情况下更喜欢使用ActiveRecord。

You can order by those two attributes in the controller method: 您可以通过controller方法中的这两个属性进行排序:

def show
  @transaction = Transaction.includes(
    team_members: [:person, :team_member_type],
    workflows: [:milestones]
  ).order('milestones.position, team_member_types.value').find(params[id])
end

Let me know if this helps. 让我知道是否有帮助。

You could create associations that include the order_by, but my experience has been that that can silently fail when eager loading, leaving you with an unordered result. 您可以创建包含order_by的关联,但是我的经验是,在渴望加载时会默默地失败,从而导致结果无序。

Although you believe, probably correctly, that ordering in Ruby would be less efficient, I would at least benchmark it. 尽管您可能正确地相信Ruby中的排序效率会降低,但我至少会对其进行基准测试。 The major performance problem is in the n + 1 query situation, and I would be optimistic that you'll find sorting in Ruby to be performant enough. 主要的性能问题是在n + 1查询情况下,我很乐观地认为您会发现Ruby中的排序足够高效。

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

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