【问题标题】:ActiveRecord includes and references queryActiveRecord 包含和引用查询
【发布时间】:2021-08-18 09:54:46
【问题描述】:

众所周知,Rails 使用“包含”和“引用”来解决 N+1 个查询。但是,我今天在测试查询时遇到了一个问题。以下是我的 rails 应用程序中的一些模型。

class Organization < ApplicationRecord
  has_many :projects, dependent: :destroy
end
class Project < ApplicationRecord
  belongs_to :organization
  has_many :routes, dependent: :destroy
end
class Route < ApplicationRecord
  belongs_to :project
end

正如我们在这里看到的,我们建立了一个嵌套关系。我的查询如下:

routes = Route.includes(project: :organization).where("organizations.name like ?", "blablabla").references(project: :organization)

这个查询可以按我的预期成功获取路由记录。不过,我也试过:

routes = Route.includes(project: :organization).where("organizations.name like ?", "blablabla").references(:projects)

routes = Route.includes(project: :organization).where("organizations.name like ?", "blablabla").references("xxxxxx")

后两个查询都可以工作并获得我想要的路线记录。据我了解,“包含”必须与“参考”一起使用。而“references”表示我们要在查询语句中加入的表。但似乎只要我将一个参数传递给“引用”,无论这个参数是什么,它都可以工作。

从 ActiveRecord 源代码来看,“引用”似乎只检查您是否传递了 table_names。

def references(*table_names)
  check_if_method_has_arguments!(:references, table_names)
  spawn.references!(*table_names)
end

def references!(*table_names) # :nodoc:
  self.references_values |= table_names
  self
end

谁能详细说明这个“参考”是如何工作的?

【问题讨论】:

  • 什么版本的导轨?
  • 在两个查询中包括加载记录 - 第一个从路由表加载所有行,然后在您访问关联时触发第二个。 references 告诉 ActiveRecord 您想在第一个查询中引用该表 - 通常是为了过滤行。
  • 无论您是否使用references,查询都有效的原因是 where 子句导致它由触发单个查询的eager_load 处理。这篇文章解释得更好然后我可以medium.com/@gandhi.nikita20/…
  • 这是 Rails 6.0.3.4
  • @max 谢谢 max,我认为这篇文章完美地回答了我的问题。但我想知道,既然“包含”加上“哪里”可以完成这项工作,为什么需要“参考”?

标签: ruby-on-rails activerecord


【解决方案1】:

由于您正在调用includes,它已经加入了这些表。如果您使用joins 加入表格,则需要references。如果您使用 joinsreferences 而不是包含,您可能会提高查询的性能。这取决于您在视图/响应中使用的是project 还是organization

【讨论】:

  • 这个答案不正确。 includes 通常会在两个不同的查询中加载记录和包含的关联。 references 告诉 rails 您需要显式连接表以过滤第一个查询中的行。将引用与.joins 一起使用绝对没有任何意义,因为连接将连接到单个查询中。 medium.com/@gandhi.nikita20/…
  • 你是对的。我是关于需要加入。参考是如果你不使用连接。
猜你喜欢
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多