2013-12-23 18:50:36 -05:00
|
|
|
class TopTopic < ActiveRecord::Base
|
|
|
|
|
|
|
|
belongs_to :topic
|
|
|
|
|
|
|
|
def self.periods
|
2013-12-27 16:16:25 -05:00
|
|
|
@periods ||= [:yearly, :monthly, :weekly, :daily]
|
2013-12-23 18:50:36 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.sort_orders
|
2013-12-27 16:16:25 -05:00
|
|
|
@sort_orders ||= [:posts, :views, :likes]
|
2013-12-23 18:50:36 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.refresh!
|
|
|
|
transaction do
|
|
|
|
# clean up the table
|
|
|
|
exec_sql("DELETE FROM top_topics")
|
|
|
|
# insert the list of all the visible topics
|
|
|
|
exec_sql("INSERT INTO top_topics (topic_id)
|
|
|
|
SELECT id
|
|
|
|
FROM topics
|
|
|
|
WHERE deleted_at IS NULL
|
|
|
|
AND visible
|
2013-12-27 12:10:35 -05:00
|
|
|
AND archetype <> :private_message
|
|
|
|
AND NOT archived",
|
|
|
|
private_message: Archetype::private_message)
|
|
|
|
|
2013-12-23 18:50:36 -05:00
|
|
|
TopTopic.periods.each do |period|
|
2013-12-27 12:10:35 -05:00
|
|
|
# update all the counter caches
|
2013-12-23 18:50:36 -05:00
|
|
|
TopTopic.sort_orders.each do |sort|
|
|
|
|
TopTopic.send("update_#{sort}_count_for", period)
|
|
|
|
end
|
2013-12-27 12:10:35 -05:00
|
|
|
# compute top score
|
|
|
|
TopTopic.compute_top_score_for(period)
|
2013-12-23 18:50:36 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.update_posts_count_for(period)
|
2014-01-02 16:38:35 -05:00
|
|
|
sql = "SELECT topic_id, GREATEST(COUNT(*), 1) AS count
|
2014-01-06 18:37:14 -05:00
|
|
|
FROM posts
|
|
|
|
WHERE created_at >= :from
|
|
|
|
AND deleted_at IS NULL
|
|
|
|
AND NOT hidden
|
2014-01-03 10:56:03 -05:00
|
|
|
AND post_type = #{Post.types[:regular]}
|
2014-01-03 11:27:55 -05:00
|
|
|
AND user_id <> #{Discourse.system_user.id}
|
2013-12-23 18:50:36 -05:00
|
|
|
GROUP BY topic_id"
|
|
|
|
|
|
|
|
TopTopic.update_top_topics(period, "posts", sql)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.update_views_count_for(period)
|
2014-01-02 19:10:17 -05:00
|
|
|
sql = "SELECT parent_id as topic_id, COUNT(*) AS count
|
2014-01-06 18:37:14 -05:00
|
|
|
FROM views
|
|
|
|
WHERE viewed_at >= :from
|
2013-12-23 18:50:36 -05:00
|
|
|
GROUP BY topic_id"
|
|
|
|
|
|
|
|
TopTopic.update_top_topics(period, "views", sql)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.update_likes_count_for(period)
|
2014-01-02 19:10:17 -05:00
|
|
|
sql = "SELECT topic_id, GREATEST(SUM(like_count), 1) AS count
|
2014-01-06 18:37:14 -05:00
|
|
|
FROM posts
|
|
|
|
WHERE created_at >= :from
|
|
|
|
AND deleted_at IS NULL
|
|
|
|
AND NOT hidden
|
2013-12-23 18:50:36 -05:00
|
|
|
GROUP BY topic_id"
|
|
|
|
|
|
|
|
TopTopic.update_top_topics(period, "likes", sql)
|
|
|
|
end
|
|
|
|
|
2013-12-27 12:10:35 -05:00
|
|
|
def self.compute_top_score_for(period)
|
2013-12-27 13:12:53 -05:00
|
|
|
# log(views) + (posts * likes)
|
2014-01-02 16:38:35 -05:00
|
|
|
exec_sql("UPDATE top_topics
|
2014-01-06 18:37:14 -05:00
|
|
|
SET #{period}_score = CASE
|
|
|
|
WHEN #{period}_views_count = 0 THEN 0
|
|
|
|
ELSE log(#{period}_views_count) + (#{period}_posts_count * #{period}_likes_count)
|
2014-01-02 16:38:35 -05:00
|
|
|
END")
|
2013-12-27 12:10:35 -05:00
|
|
|
end
|
|
|
|
|
2013-12-23 18:50:36 -05:00
|
|
|
def self.start_of(period)
|
|
|
|
case period
|
|
|
|
when :yearly then 1.year.ago
|
|
|
|
when :monthly then 1.month.ago
|
|
|
|
when :weekly then 1.week.ago
|
|
|
|
when :daily then 1.day.ago
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.update_top_topics(period, sort, inner_join)
|
|
|
|
exec_sql("UPDATE top_topics
|
|
|
|
SET #{period}_#{sort}_count = c.count
|
|
|
|
FROM top_topics tt
|
|
|
|
INNER JOIN (#{inner_join}) c ON tt.topic_id = c.topic_id
|
|
|
|
WHERE tt.topic_id = top_topics.topic_id", from: start_of(period))
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2014-02-06 19:07:36 -05:00
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: top_topics
|
|
|
|
#
|
|
|
|
# id :integer not null, primary key
|
|
|
|
# topic_id :integer
|
|
|
|
# yearly_posts_count :integer default(0), not null
|
|
|
|
# yearly_views_count :integer default(0), not null
|
|
|
|
# yearly_likes_count :integer default(0), not null
|
|
|
|
# monthly_posts_count :integer default(0), not null
|
|
|
|
# monthly_views_count :integer default(0), not null
|
|
|
|
# monthly_likes_count :integer default(0), not null
|
|
|
|
# weekly_posts_count :integer default(0), not null
|
|
|
|
# weekly_views_count :integer default(0), not null
|
|
|
|
# weekly_likes_count :integer default(0), not null
|
|
|
|
# daily_posts_count :integer default(0), not null
|
|
|
|
# daily_views_count :integer default(0), not null
|
|
|
|
# daily_likes_count :integer default(0), not null
|
|
|
|
# yearly_score :float
|
|
|
|
# monthly_score :float
|
|
|
|
# weekly_score :float
|
|
|
|
# daily_score :float
|
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
|
|
|
# index_top_topics_on_daily_likes_count (daily_likes_count)
|
|
|
|
# index_top_topics_on_daily_posts_count (daily_posts_count)
|
|
|
|
# index_top_topics_on_daily_views_count (daily_views_count)
|
|
|
|
# index_top_topics_on_monthly_likes_count (monthly_likes_count)
|
|
|
|
# index_top_topics_on_monthly_posts_count (monthly_posts_count)
|
|
|
|
# index_top_topics_on_monthly_views_count (monthly_views_count)
|
|
|
|
# index_top_topics_on_topic_id (topic_id) UNIQUE
|
|
|
|
# index_top_topics_on_weekly_likes_count (weekly_likes_count)
|
|
|
|
# index_top_topics_on_weekly_posts_count (weekly_posts_count)
|
|
|
|
# index_top_topics_on_weekly_views_count (weekly_views_count)
|
|
|
|
# index_top_topics_on_yearly_likes_count (yearly_likes_count)
|
|
|
|
# index_top_topics_on_yearly_posts_count (yearly_posts_count)
|
|
|
|
# index_top_topics_on_yearly_views_count (yearly_views_count)
|
|
|
|
#
|