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

时间:2014-05-28 01:12:21

标签: ruby-on-rails ruby database performance

如果我有一个包含许多帖子的用户模型,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?这一事实是否会产生任何魔力?用户?

1 个答案:

答案 0 :(得分:2)

  

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

如果您不使用.includes(),那么您将拥有所谓的N + 1查询。即必须查找第一个项目,然后再查看N个项目。使用.includes()会在执行时急切地将post对象加​​载到内存中。执行时间将在您调用执行查询的位置时...在使用has_posted?方法的示例中,执行点将为posts.any?

<强>更新

但是,这是一个更好的方法!即使用数据库查询而不是循环使用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个查询,瞧! (在控制台上运行此命令并观察每种方法生成的查询。)