我有一个拥有约1000个俱乐部和10,000个用户的数据库。我需要建立一个连续显示每个俱乐部的表格,其中包含与该俱乐部相关的用户数量,帖子和评论的列。我现在的查询是这样的(来自我的控制器):
@clubs.find_each do |club|
@users.where(:club_id => club.club_id).find_each do |user|
@numPostsByClub += user.posts.count
@numCommentsByClub += user.comments.count
现在我想必须有一种更有效的方法来实现这一点,因为我的页面加载需要大约90秒。是否有更有效的方法来加载所有这些数据,或者可能是一种运行rake任务的方法(我只需要每天更新一次数据)来存储所有这些以便快速访问?
答案 0 :(得分:1)
如果我理解正确,您需要俱乐部的评论总数和俱乐部的评论总数。
counter_cache 如果您想快速解答以下问题,可以为您提供帮助:
但不是每个俱乐部的帖子或评论总数(尽管它会让你的生活更容易)。
免责声明:在未创建数据库备份且未阅读完整答案的情况下,请勿开始将以下建议投入生产。
要通过在club table中添加2列来更快地启动脚本:
class AddCommentsCountToClubs < ActiveRecord::Migration
def change
add_column :clubs, :comments_count, :integer, default: 0
end
end
class AddPostsCountToClubs < ActiveRecord::Migration
def change
add_column :clubs, :posts_count, :integer, default: 0
end
end
对于每个俱乐部:
要创建将更新计数器的rake任务,请添加包含以下内容的文件lib/tasks/update_clubs_counters.rake
:
namespace :db do
task :update_clubs_counters => :environment do
Club.all.each do |club|
club.update(comments_count: club.comments.count, posts_count: club.posts.count)
end
end
end
创建文件后运行bundle exec rake db:update_clubs_counters
更新计数器的另一种方法是使用rails控制台并运行任务的内容(仅与更新相关的部分)
然后,对于评论和发布模型,添加2个回调来增加/减少每个相应俱乐部的计数器。
为清楚起见,我将定义所涉及的所有模型及其之间的关系
class Club < ActiveRecord::Base
has_many :users
has_many :comments, through: :users
has_many :posts, through: :users
end
class User < ActiveRecord::Base
belongs_to :club
has_many :posts
end
class Comment < ActiveRecord::Base
belongs_to :user
after_create :increment_club_comments_count
after_destroy :decrement_club_comments_count
def increment_club_comments_count
Club.increment_counter( :comments_count, user.club_id )
end
def decrement_club_comments_count
Club.decrement_counter( :comments_count, user.club_id )
end
end
class Post < ActiveRecord::Base
belongs_to :user
after_create :increment_club_posts_count
after_destroy :decrement_club_posts_count
def increment_club_posts_count
Club.increment_counter( :posts_count, user.club_id )
end
def decrement_club_posts_count
Club.decrement_counter( :posts_count, user.club_id )
end
end
现在,每次添加/删除帖子/评论时,俱乐部表中的相应计数器都会递增/递减。
您可以像这样简化控制器(只有一个查询,您将拥有所有数据):
@clubs = Club.all # I recommend to use pagination and not to list all 1000 clubs at once
在您的视图中,您只需显示您的计数器:
<% @clubs.each do |club| %>
<p>Comments Count: <%= club.comments_count %></p>
<p>Posts Count: <%= club.posts_count %></p>
<% end %>
您可以找到有关increment_counter和decrement_counter以及counter_cache with has_many :through
的更多详细信息答案 1 :(得分:0)
查看counter_cache
关联的belongs_to
选项。这会向父模型添加一个字段以缓存子对象的数量。创建或删除子对象时,将更新此字段以保持正确的计数。
可以在Ruby on Rails指南的Association Basics部分找到更多信息。
RailsCasts还有一个关于counter_cache
选项的剧集,其中有一个示例实现:Example #23