我的评分系统很简单,用户喜欢或不喜欢这篇文章。
基本上,我有这样的东西,而且效果很好:
class Article
has_many :ratings
def self.by_ratings
all.sort_by{|article| (article.ratings.where(like: true).size).to_f / (article.ratings.size) }
end
end
如您所料,我们的应用在数据库中变得庞大,流量增加,这部分代码成为瓶颈。
我正在尝试用纯 sql 重写它以提高性能。我还试图将其作为 ActiveRelation 与其他条件链接起来。也尝试编写 sql 但没有成功。有什么想法吗?
谢谢!
使用:
- rails 3.0.10
- 事件记录
- Sqlite 3(我们可以切换到 Postgresql)
最佳答案
您需要的是缓存列。
1) 创建迁移以访问缓存列:
class AddRatingCacheToArticles < ActiveRecord::Migration
def self.up
add_column :articles, :rating_cache, :decimal, :default => 0.0
end
def self.down
remove_column :articles, :rating_cache
end
end
2) 在 Article
中定义一个更新方法,它将进行计数:
class Article < ActiveRecord::Base
has_many :ratings
def update_rating_cache
current_rating = ratings.where(:like => true).count.to_f/ratings.count.to_f
update_attribute(:rating_cache, current_rating)
end
end
3) 在 Rating
中设置一个回调,以便在它们被保存时触发 update_rating_cache
方法:
class Rating < ActiveRecord::Base
belongs_to :article
after_save :update_article_rating_cache
after_destroy :update_article_rating_cache
def update_article_rating_cache
article.update_rating_cache if article
end
end
4) 现在可以非常轻松地按评分对文章进行排序:
class Article < ActiveRecord::Base
has_many :ratings
def self.by_ratings
order('rating_cache DESC')
end
def update_rating_cache
current_rating = ratings.where(:like => true).count.to_f/ratings.count.to_f
update_attribute(:rating_cache, current_rating)
end
end
这可以用作 ActiveRelation!
祝你好运:)
关于ruby-on-rails - rails 3 : Sort a ActiveRelation by Ratings Counted from another table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7242470/