当查询使用包含时,Rails 如何处理 has_many?

2024-02-26

如果我有一个包含许多帖子的用户模型,那么在以下场景中,Rails 将对数据库执行多少个查询?

class User
  has_many :posts

  # this is the main method in question...
  def has_posted?
    posts.any? {|p| p.posted? }
  end
end

# has an attr "posted" which is a boolean
class Post
  belongs_to :user
end


# some controller
users = User.includes(:posts).all


# in the view
<% users.each do |user| %>
  <%= 'posted!' if user.has_posted? %>
<% end %>

我正在使用的事实是否includes在初始查询中,当我循环遍历返回的帖子时,会产生任何魔法吗?has_posted?防止对每个用户的帖子表进行多次查找的方法?


当我循环遍历 has_posted 中返回的帖子时,我在初始查询中使用 include 的事实是否有任何魔力?防止对每个用户的帖子表进行多次查找的方法?

Yes.

如果您不使用.includes()您将得到所谓的 N+1 查询。 IE。必须查找第一项以及后面的 N 个项目。使用.includes()将在执行时将 post 对象加载到内存中。执行时间将是您调用执行查询的内容时...在您的示例中has_posted?方法,执行点将是posts.any?.

UPDATE

然而,这里有一个更好的方法来做到这一点!即使用数据库查询而不是使用 ruby​​ 循环遍历帖子集合。像这样:

class User
  def has_posted?
    posts.is_posted.any?
  end
end

class Post
  scope :is_posted, -> { where(posted: true) }
end

通过这种方式,您可以让数据库仅选择那些具有以下内容的帖子posted设置为 true。然后是.any?会将查询转换为 COUNT 查询,瞧! (在控制台上运行它并观察每种方法生成的查询。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当查询使用包含时,Rails 如何处理 has_many? 的相关文章