如果我有一个包含许多帖子的用户模型,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 %>
当我循环遍历has_posted中返回的帖子时,我在初始查询中使用包含的事实是否有任何魔力?防止每个用户对posts表进行多次查找的方法?
最佳答案
Does the fact that I’m using includes in the initial query do any magic when I loop over the returned posts in the has_posted? method to prevent multiple lookups against the posts table for each user?
是.
如果你不使用.includes(),你将拥有所谓的N 1查询.即必须查找第一个项目,然后再查看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
通过这种方式,您可以使数据库仅选择已发布设置为true的帖子.然后是.any?将查询转换为COUNT查询,瞧! (在控制台上运行此命令并观察每种方法生成的查询.)