2017-03-31 49 views
0

我有一个显示大量数据的页面,我正在优化它,并且我努力通过在订单中获取正确的数据来平衡减少的DB查询我需要。Rails 4+,儿童父记录的订购清单

Transaction是顶级元素,并且每个transaction具有多个workflows并且每个workflow有许多milestones。我通过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 

在我的控制器,这是我有:

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

此收集所有我需要在1所DB查询的数据,但问题是,当我遍历里程碑的工作流程,我需要按position属性对其进行排序。

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

如果我将其与N+1问题写的,它应该是这样的:

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

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

我也用team_member_type.value属性对team_members进行排序,但这与上面的问题相同。

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

我的主要目标是效率。如果我需要使用一些查询对象来清理它和原始SQL,那我可以,我只是不太熟练SQL,并且如果合理的话,更喜欢使用ActiveRecord。

回答

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 

让我知道,如果这有助于。

0

您可以创建包含order_by的关联,但是我的经验是,如果在加载时发生沉默失败,则会导致无序结果。

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