Discourseで「トップ」トピックを計算する

:bookmark: これは、Discourseにおいて「トップ」でフィルタリングされたトピックがどのように「トップトピック」と決定されるかを説明するリファレンスガイドです。

:person_raising_hand: 必要なユーザーレベル: 全ユーザー

Discourseサイトには、ユーザーがトピックを「トップ」でソートできる機能があります。このガイドでは、「トップ」トピックがどのように計算され、表示されるかを説明します。

概要

  • すべての「トップ」トピックには「トップスコア」が割り当てられます
  • スコアは、選択された期間内の「いいね」、返信、および閲覧数に基づいています
  • 「トップスコア」が最も高いトピックがリストの最上位に表示されます

トップスコアの計算

トピックの「トップスコア」は、以下の要因を使用して計算されます。

  1. 閲覧数
  2. 最初の投稿への「いいね」数
  3. 後続の投稿への「いいね」数
  4. 返信数

計算では、3つの非表示サイト設定が乗数として使用されます(これらは管理者設定UIには表示されませんが、RailsコンソールまたはAPI経由で変更できます)。

  • top topics formula log views multiplier (デフォルト: 2)
  • top topics formula first post likes multiplier (デフォルト: 0.5)
  • top topics formula least likes per post multiplier (デフォルト: 3)

計算手順

各トピックについて、次の合計を計算してトップスコアを求めます。

  1. 選択された期間における各トピックの閲覧数の対数(最小1)を、log views multiplierで乗算したもの
  2. トピックの元の投稿に対する「いいね」の数を、first post likes multiplierで乗算したもの
  3. 次のいずれか小さい方の値:
    • 投稿ごとの平均「いいね」数(トピックの合計「いいね」数 / 投稿数)
    • least likes per post multiplierの値
  4. 期間内の投稿数が10未満の場合、次の計算を実行します。
    0 - ((10 - トピック内の投稿数) / 20) * 元の投稿への「いいね」数
    
    それ以外の場合は、10
  5. トピックの投稿数の対数(最小1)

トップトピックの表示

Discourseサイトでのトップトピックの例は、以下の画像で確認できます。

追加リソース

詳細な技術情報については、以下を参照してください。

-- [params]
-- date :start_date = 26 apr 2020
-- date :end_date = 2 may 2020
-- double :log_views_multiplier = 2.0
-- double :first_post_likes_multiplier = 0.5
-- double :least_likes_per_post_multiplier = 3.0

WITH likes AS (
SELECT topic_id, SUM(like_count) AS count
FROM posts
WHERE created_at::date >= :start_date::date 
  AND created_at::date < :end_date::date
  AND deleted_at IS NULL
  AND NOT hidden
  AND post_type = 1
GROUP BY topic_id
),
op_likes AS (
SELECT topic_id, like_count AS count
FROM posts
WHERE created_at::date >= :start_date::date 
  AND created_at::date < :end_date::date
  AND post_number = 1
  AND deleted_at IS NULL
  AND NOT hidden
  AND post_type = 1
),
posts AS (
SELECT topic_id, GREATEST(COUNT(*), 1) AS count
FROM posts
WHERE created_at::date >= :start_date::date 
  AND created_at::date < :end_date::date
  AND deleted_at IS NULL
  AND NOT hidden
  AND post_type = 1
  AND user_id <> 0
GROUP BY topic_id
),
views AS (
SELECT topic_id, COUNT(*) AS count
FROM topic_views
WHERE viewed_at::date >= :start_date::date 
  AND viewed_at::date < :end_date::date
GROUP BY topic_id
),
category_definition_topic_ids AS (
  SELECT COALESCE(topic_id, 0) AS id FROM categories
),
top_topics AS(
SELECT 
topics.id AS topic_id,
topics.title,
topics.user_id, 
posts.count AS date_range_posts,
views.count AS date_range_views,
topics.views AS all_time_views,
topics.bumped_at,
(CASE
 WHEN topics.created_at::date < :start_date::date 
  AND topics.created_at::date >= :end_date::date
 THEN 0
 ELSE log(GREATEST(views.count, 1)) * :log_views_multiplier +
    op_likes.count * :first_post_likes_multiplier +
    CASE WHEN likes.count > 0 AND posts.count > 0
       THEN
        LEAST(likes.count / posts.count, :least_likes_per_post_multiplier)
       ELSE 0
    END +
    CASE WHEN topics.posts_count < 10 THEN
       0 - ((10 - topics.posts_count) / 20) * op_likes.count
    ELSE
       10
    END +
    log(GREATEST(posts.count, 1))
 END) AS score
FROM posts
INNER JOIN views ON posts.topic_id = views.topic_id
INNER JOIN likes ON posts.topic_id = likes.topic_id
INNER JOIN op_likes ON posts.topic_id = op_likes.topic_id
LEFT JOIN topics ON topics.id = posts.topic_id AND topics.deleted_at IS NULL
WHERE topics.deleted_at IS NULL
  AND topics.visible
  AND topics.archetype <> 'private_message'
  AND NOT topics.archived
  AND topics.id NOT IN (SELECT id FROM category_definition_topic_ids)
ORDER BY
  score DESC,
  topics.bumped_at DESC
)

SELECT * FROM top_topics WHERE score > 0
「いいね!」 12

この計算に「票」を含めることは可能ですか?

これらは非表示になったため、サイト設定では表示されなくなりました。