如果我有一个包含许多帖子的用户模型,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?
这一事实是否会产生任何魔力?用户?
答案 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个查询,瞧! (在控制台上运行此命令并观察每种方法生成的查询。)