Rails 4+,由儿童排序父记录列表

时间:2017-03-31 18:02:15

标签: ruby-on-rails activerecord query-optimization

我有一个显示大量数据的页面,我正在努力优化它,我正在努力平衡减少数据库查询,并按照我需要的顺序获取正确的数据。

Transaction是顶级元素,每个transaction都有多个workflows,每个workflow都有多个milestones。我按workflows属性订购milestonesposition:integer

# 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

在我的控制器中,这就是我所拥有的:

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

这会在1个数据库查询中收集我需要的所有数据,但问题是当我迭代工作流的里程碑时,我需要按position属性进行排序。

我可以从数据库中获取数据,然后使用Ruby对其进行排序,但这似乎效率低下,我更愿意在数据库中正确完成(如果可能的话)。

如果我用N+1问题写它,它看起来像这样:

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

我认为每个人都认为这是一个坏主意,但我正在努力弄清楚如何对数据进行排序并同时优化我的数据库调用。

我还会根据team_members属性对team_member_type.value进行排序,但这与上述问题相同。

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

我的主要目标是效率。如果我需要使用一些Query对象来清理它和原始SQL,我很好,我只是不是非常精通SQL,如果合理的话,我更喜欢使用ActiveRecord。

2 个答案:

答案 0 :(得分:0)

您可以通过控制器方法中的这两个属性进行排序:

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

如果有帮助,请告诉我。

答案 1 :(得分:0)

您可以创建包含order_by的关联,但我的经验是,在急切加载时可能会无声地失败,从而使您无法获得结果。

虽然您可能正确地相信Ruby中的排序效率会降低,但我至少会对其进行基准测试。主要的性能问题是在n + 1查询情况下,我会乐观地认为你在Ruby中找到足够高的排序。