急切加载不使用rails中的order()子句

时间:2017-09-25 23:54:50

标签: ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord eager-loading

我正在使用此查询来获取我的数据

user = User.includes(:skills).order(user: :id)

工作正常。但是当我尝试按照下面的字母顺序显示技能时

user.skills.order(name: :asc)

它在日志中显示它进入数据库,因为order()activerecord方法。似乎eager loading在这里失败了,因为无论如何它必须进入数据库才能使用急切加载。

任何人都可以指导我做这件事的好方法。

3 个答案:

答案 0 :(得分:5)

当您急切地使用.includes加载关联记录时,您应该按原样访问关联。否则,如果向关联添加更多查询条件,则会导致新的数据库查询。

有几种方法可以订购相关的预先加载的记录。

<强> 1。将订单条件添加到主要范围。

user = User.includes(:skills).order("users.id, skills.name ASC")

在这种情况下,它默认情况下不会像include方法一样工作,进行两次查询。将使用“LEFT OUTER JOIN”执行一个查询以获取关联的记录。这相当于使用eager_load方法而不是includes

user = User.eager_load(:skills).order("users.id, skills.name ASC")

<强> 2。在定义时将订单条件添加到关联。

在这种情况下,无论何时访问关联,关联的记录将始终按名称排序。

class User < ActiveRecord::Base
  has_many :skills, -> { order(:name) }
end

第3。创建另一个包含所需订单的关联,仅在此特定情况下使用。

这使您可以避免主关联上的不必要条件skills

class User < ActiveRecord::Base
  has_many :skills_ordered_by_name, -> { order(:name) }, class_name: "Skill"
end

# usage
users = User.includes(:skills_ordered_by_name)

users.each do |user|
  # access eager loaded association
  user.skills_ordered_by_name
end

<强> 4。设置关联模型的默认顺序。

这将导致条件应用于与关联模型相关的每个关联和查询。

class Skill < ActiveRecord::Base
  default_scope { order(:name) }
end

<强> 5。使用Ruby代码(不是ActiveRecord查询方法)对急切加载的记录进行排序

当要排序的记录不多时,这种方法是合适的。

users = User.includes(:skills)

users.each do |user|
  # sorting with Ruby's 'sort_by' method
  user.skills.sort_by(&:name)

  # or something like
  user.skills.sort { |one, another| one.name <=> another.name }
end

答案 1 :(得分:0)

您可以使用:

user = User.includes(:skills).order(user: :id, name: :desc)

答案 2 :(得分:0)

您可以使用内置方法ActiveRecord::Associations::Preloader#preload获得灵活性。

它接受三个参数:

SELECT 
    [Extent1].[Department_Id] AS [Department_Id], 
    [Extent1].[Department_Title] AS [Department_Title], 
    [Extent1].[Status] AS [Status], 
    [Extent1].[Date_Created] AS [Date_Created], 
    [Extent1].[Date_Modified] AS [Date_Modified]
    FROM [dbo].[Departments] AS [Extent1]
    ORDER BY [Extent1].[Department_Title] DESC

第一个参数接受preload(records, associations, preload_scope = nil) 个记录或记录数组。 第二个是要预加载到第一个参数中指定的记录的一个或多个关联。 最后是ActiveRecord::BaseHash,它们已与关联合并。

使用第三个参数获取排序和预加载的关联:

Relation