Rails急切加载计数?

Bri*_*ong 15 ruby-on-rails

使用include属性可以很好地加载

Post.find(:all, :include => :author)
Run Code Online (Sandbox Code Playgroud)

我想知道你是否也可以急于加载计数,比如我想获得每个帖子的评论数量,而不加载所有评论本身?

也许是这样的

Post.find(:all, :include => [:author, "count(comments)")
Run Code Online (Sandbox Code Playgroud)

我想我可以使用count_cache列.但如果有可能的话,在一个包含中做这一切真的很美.

额外的奖励积分,如果有人可以展示如何不仅得到计数,但也提出一些条件,例如只有已经批准的帖子的数量.

Chr*_*her 26

他们应该已经加载使用

post.comments.length
Run Code Online (Sandbox Code Playgroud)

我遇到了同样的问题,因为我使用的是.count

  • 我认为这不是他想要的.这将加载评论关联中的所有条目,然后对它们进行计数.他希望使用SQL来急切地拉取计数而不加载对象.(或者至少我是这样理解的). (2认同)

Rya*_*yan 5

根据 avaynshtok 的回答,以下技术应该只进行 2 次数据库调用。

# ./app/controllers/posts_controller.rb

def index
  # First load the posts
  @posts = Post.all

  # Then you can load a hash of author counts grouped by post_id
  # Rails 4 version:
  @comment_counts = Comment.group(:post_id).count
  # Rails 3 version:
  # @comment_counts = Comment.count(:group => :post_id)
end
Run Code Online (Sandbox Code Playgroud)

那么在你看来

<!-- ./app/views/posts/index.html.erb  -->

<% @posts.each do |post| %>
  <!-- reference the count by the post.id -->
  post_count: <%= @comment_counts[post.id] %>
<% end %>
Run Code Online (Sandbox Code Playgroud)


小智 -8

至少在 MySQL 中,将这些作为两个单独的调用来执行会更快,因为您可以避免连接。我知道这并不能回答你的问题,但看起来你正在努力获得更好的速度并做

Post.find ...
Run Code Online (Sandbox Code Playgroud)

然后

post.comments.count
Run Code Online (Sandbox Code Playgroud)

与在一个查询中检索两者相比,速度更快、内存效率更高(对于数据库而言)。

  • 嗯,使用预加载的主要原因之一是避免 N+1 查询。 (5认同)
  • 这会引发 N+1 查询,但不会回答问题。 (4认同)