mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 20:02:46 +08:00
FIX: actually compute top score for 'older' periods
This commit is contained in:
parent
36f081bf43
commit
a62968c846
|
@ -2,37 +2,23 @@ class TopTopic < ActiveRecord::Base
|
||||||
|
|
||||||
belongs_to :topic
|
belongs_to :topic
|
||||||
|
|
||||||
def self.periods
|
|
||||||
@periods ||= [:yearly, :monthly, :weekly, :daily]
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.sort_orders
|
|
||||||
@sort_orders ||= [:posts, :views, :likes]
|
|
||||||
end
|
|
||||||
|
|
||||||
# The top topics we want to refresh often
|
# The top topics we want to refresh often
|
||||||
def self.refresh_daily!
|
def self.refresh_daily!
|
||||||
transaction do
|
transaction do
|
||||||
remove_invisible_topics
|
remove_invisible_topics
|
||||||
add_new_visible_topics
|
add_new_visible_topics
|
||||||
|
|
||||||
TopTopic.sort_orders.each do |sort|
|
update_counts_and_compute_scores_for(:daily)
|
||||||
TopTopic.send("update_#{sort}_count_for", :daily)
|
|
||||||
end
|
|
||||||
TopTopic.compute_top_score_for(:daily)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# We don't have to refresh these as often
|
# We don't have to refresh these as often
|
||||||
def self.refresh_older!
|
def self.refresh_older!
|
||||||
older = TopTopic.periods - [:daily]
|
older_periods = TopTopic.periods - [:daily]
|
||||||
|
|
||||||
transaction do
|
transaction do
|
||||||
older.each do |period|
|
older_periods.each do |period|
|
||||||
TopTopic.sort_orders.each do |sort|
|
update_counts_and_compute_scores_for(period)
|
||||||
TopTopic.send("update_#{sort}_count_for", :daily)
|
|
||||||
end
|
|
||||||
TopTopic.compute_top_score_for(:daily)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,115 +28,132 @@ class TopTopic < ActiveRecord::Base
|
||||||
TopTopic.refresh_older!
|
TopTopic.refresh_older!
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.remove_invisible_topics
|
private
|
||||||
exec_sql("WITH category_definition_topic_ids AS (
|
|
||||||
SELECT COALESCE(topic_id, 0) AS id FROM categories
|
|
||||||
), invisible_topic_ids AS (
|
|
||||||
SELECT id
|
|
||||||
FROM topics
|
|
||||||
WHERE deleted_at IS NOT NULL
|
|
||||||
OR NOT visible
|
|
||||||
OR archetype = :private_message
|
|
||||||
OR archived
|
|
||||||
OR id IN (SELECT id FROM category_definition_topic_ids)
|
|
||||||
)
|
|
||||||
DELETE FROM top_topics
|
|
||||||
WHERE topic_id IN (SELECT id FROM invisible_topic_ids)",
|
|
||||||
private_message: Archetype::private_message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.add_new_visible_topics
|
def self.periods
|
||||||
exec_sql("WITH category_definition_topic_ids AS (
|
@@periods ||= [:yearly, :monthly, :weekly, :daily].freeze
|
||||||
SELECT COALESCE(topic_id, 0) AS id FROM categories
|
|
||||||
), visible_topics AS (
|
|
||||||
SELECT t.id
|
|
||||||
FROM topics t
|
|
||||||
LEFT JOIN top_topics tt ON t.id = tt.topic_id
|
|
||||||
WHERE t.deleted_at IS NULL
|
|
||||||
AND t.visible
|
|
||||||
AND t.archetype <> :private_message
|
|
||||||
AND NOT t.archived
|
|
||||||
AND t.id NOT IN (SELECT id FROM category_definition_topic_ids)
|
|
||||||
AND tt.topic_id IS NULL
|
|
||||||
)
|
|
||||||
INSERT INTO top_topics (topic_id)
|
|
||||||
SELECT id FROM visible_topics",
|
|
||||||
private_message: Archetype::private_message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.update_posts_count_for(period)
|
|
||||||
sql = "SELECT topic_id, GREATEST(COUNT(*), 1) AS count
|
|
||||||
FROM posts
|
|
||||||
WHERE created_at >= :from
|
|
||||||
AND deleted_at IS NULL
|
|
||||||
AND NOT hidden
|
|
||||||
AND post_type = #{Post.types[:regular]}
|
|
||||||
AND user_id <> #{Discourse.system_user.id}
|
|
||||||
GROUP BY topic_id"
|
|
||||||
|
|
||||||
TopTopic.update_top_topics(period, "posts", sql)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.update_views_count_for(period)
|
|
||||||
sql = "SELECT topic_id, COUNT(*) AS count
|
|
||||||
FROM topic_views
|
|
||||||
WHERE viewed_at >= :from
|
|
||||||
GROUP BY topic_id"
|
|
||||||
|
|
||||||
TopTopic.update_top_topics(period, "views", sql)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.update_likes_count_for(period)
|
|
||||||
sql = "SELECT topic_id, GREATEST(SUM(like_count), 1) AS count
|
|
||||||
FROM posts
|
|
||||||
WHERE created_at >= :from
|
|
||||||
AND deleted_at IS NULL
|
|
||||||
AND NOT hidden
|
|
||||||
AND post_type = #{Post.types[:regular]}
|
|
||||||
GROUP BY topic_id"
|
|
||||||
|
|
||||||
TopTopic.update_top_topics(period, "likes", sql)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.compute_top_score_for(period)
|
|
||||||
sql = <<-SQL
|
|
||||||
WITH top AS (
|
|
||||||
SELECT CASE
|
|
||||||
WHEN topics.created_at < :from THEN 0
|
|
||||||
ELSE log(greatest(#{period}_views_count, 1)) + #{period}_likes_count + #{period}_posts_count * 2
|
|
||||||
END AS score,
|
|
||||||
topic_id
|
|
||||||
FROM top_topics
|
|
||||||
LEFT JOIN topics ON topics.id = top_topics.topic_id
|
|
||||||
)
|
|
||||||
UPDATE top_topics
|
|
||||||
SET #{period}_score = top.score
|
|
||||||
FROM top
|
|
||||||
WHERE top_topics.topic_id = top.topic_id
|
|
||||||
AND #{period}_score <> top.score
|
|
||||||
SQL
|
|
||||||
|
|
||||||
exec_sql(sql, from: start_of(period))
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
||||||
end
|
|
||||||
|
|
||||||
def self.update_top_topics(period, sort, inner_join)
|
def self.sort_orders
|
||||||
exec_sql("UPDATE top_topics
|
@@sort_orders ||= [:posts, :views, :likes].freeze
|
||||||
SET #{period}_#{sort}_count = c.count
|
end
|
||||||
FROM top_topics tt
|
|
||||||
INNER JOIN (#{inner_join}) c ON tt.topic_id = c.topic_id
|
def self.update_counts_and_compute_scores_for(period)
|
||||||
WHERE tt.topic_id = top_topics.topic_id
|
TopTopic.sort_orders.each do |sort|
|
||||||
AND tt.#{period}_#{sort}_count <> c.count",
|
TopTopic.send("update_#{sort}_count_for", period)
|
||||||
from: start_of(period))
|
end
|
||||||
end
|
TopTopic.compute_top_score_for(period)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.remove_invisible_topics
|
||||||
|
exec_sql("WITH category_definition_topic_ids AS (
|
||||||
|
SELECT COALESCE(topic_id, 0) AS id FROM categories
|
||||||
|
), invisible_topic_ids AS (
|
||||||
|
SELECT id
|
||||||
|
FROM topics
|
||||||
|
WHERE deleted_at IS NOT NULL
|
||||||
|
OR NOT visible
|
||||||
|
OR archetype = :private_message
|
||||||
|
OR archived
|
||||||
|
OR id IN (SELECT id FROM category_definition_topic_ids)
|
||||||
|
)
|
||||||
|
DELETE FROM top_topics
|
||||||
|
WHERE topic_id IN (SELECT id FROM invisible_topic_ids)",
|
||||||
|
private_message: Archetype::private_message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.add_new_visible_topics
|
||||||
|
exec_sql("WITH category_definition_topic_ids AS (
|
||||||
|
SELECT COALESCE(topic_id, 0) AS id FROM categories
|
||||||
|
), visible_topics AS (
|
||||||
|
SELECT t.id
|
||||||
|
FROM topics t
|
||||||
|
LEFT JOIN top_topics tt ON t.id = tt.topic_id
|
||||||
|
WHERE t.deleted_at IS NULL
|
||||||
|
AND t.visible
|
||||||
|
AND t.archetype <> :private_message
|
||||||
|
AND NOT t.archived
|
||||||
|
AND t.id NOT IN (SELECT id FROM category_definition_topic_ids)
|
||||||
|
AND tt.topic_id IS NULL
|
||||||
|
)
|
||||||
|
INSERT INTO top_topics (topic_id)
|
||||||
|
SELECT id FROM visible_topics",
|
||||||
|
private_message: Archetype::private_message)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.update_posts_count_for(period)
|
||||||
|
sql = "SELECT topic_id, GREATEST(COUNT(*), 1) AS count
|
||||||
|
FROM posts
|
||||||
|
WHERE created_at >= :from
|
||||||
|
AND deleted_at IS NULL
|
||||||
|
AND NOT hidden
|
||||||
|
AND post_type = #{Post.types[:regular]}
|
||||||
|
AND user_id <> #{Discourse.system_user.id}
|
||||||
|
GROUP BY topic_id"
|
||||||
|
|
||||||
|
TopTopic.update_top_topics(period, "posts", sql)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.update_views_count_for(period)
|
||||||
|
sql = "SELECT topic_id, COUNT(*) AS count
|
||||||
|
FROM topic_views
|
||||||
|
WHERE viewed_at >= :from
|
||||||
|
GROUP BY topic_id"
|
||||||
|
|
||||||
|
TopTopic.update_top_topics(period, "views", sql)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.update_likes_count_for(period)
|
||||||
|
sql = "SELECT topic_id, GREATEST(SUM(like_count), 1) AS count
|
||||||
|
FROM posts
|
||||||
|
WHERE created_at >= :from
|
||||||
|
AND deleted_at IS NULL
|
||||||
|
AND NOT hidden
|
||||||
|
AND post_type = #{Post.types[:regular]}
|
||||||
|
GROUP BY topic_id"
|
||||||
|
|
||||||
|
TopTopic.update_top_topics(period, "likes", sql)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.compute_top_score_for(period)
|
||||||
|
sql = <<-SQL
|
||||||
|
WITH top AS (
|
||||||
|
SELECT CASE
|
||||||
|
WHEN topics.created_at < :from THEN 0
|
||||||
|
ELSE log(greatest(#{period}_views_count, 1)) + #{period}_likes_count + #{period}_posts_count * 2
|
||||||
|
END AS score,
|
||||||
|
topic_id
|
||||||
|
FROM top_topics
|
||||||
|
LEFT JOIN topics ON topics.id = top_topics.topic_id
|
||||||
|
)
|
||||||
|
UPDATE top_topics
|
||||||
|
SET #{period}_score = top.score
|
||||||
|
FROM top
|
||||||
|
WHERE top_topics.topic_id = top.topic_id
|
||||||
|
AND #{period}_score <> top.score
|
||||||
|
SQL
|
||||||
|
|
||||||
|
exec_sql(sql, from: start_of(period))
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
AND tt.#{period}_#{sort}_count <> c.count",
|
||||||
|
from: start_of(period))
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user