默认徽章查询

这是默认徽章的 SQL 查询及其触发信息(在可用时)的参考指南。

核心徽章

:2nd_place_medal: 周年纪念

(这个徽章在日期选择上有一些额外的后端魔法,但我还是会将其包含在内)

 start_date = start_date.iso8601(6)
    end_date = end_date.iso8601(6)

      SELECT u.id
        FROM users AS u
        JOIN posts AS p ON p.user_id = u.id
        JOIN topics AS t ON p.topic_id = t.id
       WHERE u.id > 0
         AND u.active
         AND NOT u.staged
         AND (u.silenced_till IS NULL OR u.silenced_till < '#{start_date}')
         AND (u.suspended_till IS NULL OR u.suspended_till < '#{start_date}')
         AND u.created_at <= '#{start_date}'
         AND NOT p.hidden
         AND p.deleted_at IS NULL
         AND p.created_at BETWEEN '#{start_date}' AND '#{end_date}'
         AND t.visible
         AND t.archetype <> 'private_message'
         AND t.deleted_at IS NULL
         AND NOT EXISTS (SELECT 1 FROM user_badges AS ub WHERE ub.user_id = u.id AND ub.badge_id = #{Badge::Anniversary} AND ub.granted_at BETWEEN '#{start_date}' AND '#{end_date}')
         AND NOT EXISTS (SELECT 1 FROM anonymous_users AS au WHERE au.user_id = u.id)
       GROUP BY u.id
      HAVING COUNT(p.id) > 0
每日运行撤销查询
查询目标帖子
触发器 每日更新

:3rd_place_medal: 受赞赏(多个帖子的点赞数)

:3rd_place_medal: 受赞赏、:2nd_place_medal: 受尊敬 和 :1st_place_medal: 受钦佩 徽章遵循相同的模式,但 p.like_countHAVING COUNT(*) 的值不同。

SELECT p.user_id, CURRENT_TIMESTAMP AS granted_at
      FROM posts AS p
      WHERE p.like_count >= #{like_count}
        AND (:backfill OR p.user_id IN (:user_ids))
      GROUP BY p.user_id
      HAVING COUNT(*) > #{post_count}
每日运行撤销查询
查询目标帖子
触发器 每日更新

:3rd_place_medal: 自传作者

SELECT u.id user_id, CURRENT_TIMESTAMP granted_at
    FROM users u
    JOIN user_profiles up on u.id = up.user_id
    WHERE bio_raw IS NOT NULL AND LENGTH(TRIM(bio_raw)) > 10 AND
          uploaded_avatar_id IS NOT NULL AND
          (:backfill OR u.id IN (:user_ids) )
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 当用户被编辑或创建时

:3rd_place_medal: 基础(信任等级)

:3rd_place_medal: 基础、:3rd_place_medal: 成员、:2nd_place_medal: 常规、:1st_place_medal: 领袖 徽章都遵循相同的模式,但 trust_level 值不同。

SELECT u.id user_id, current_timestamp granted_at FROM users u
      WHERE trust_level >= #{level.to_i} AND (
        :backfill OR u.id IN (:user_ids)
      )
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 当用户更改信任等级时

:3rd_place_medal: 认证 和 :2nd_place_medal: 许可

这些徽章没有 SQL 查询。它们是 Discourse Narrative Bot 的一部分,当用户完成交互式教程(Discobot)时通过编程方式授予。


:3rd_place_medal: 编辑者

 SELECT p.user_id, min(p.id) post_id, min(p.created_at) granted_at
    FROM badge_posts p
    WHERE p.self_edits > 0 AND
        (:backfill OR p.id IN (:post_ids) )
    GROUP BY p.user_id
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 当用户编辑或创建帖子时

:3rd_place_medal: 爱好者

:3rd_place_medal: 爱好者、:2nd_place_medal: 鉴赏家 和 :1st_place_medal: 狂热者 徽章遵循相同的模式,但 HAVING COUNT(*) 阈值不同。

WITH consecutive_visits AS (
        SELECT user_id
             , visited_at
             , visited_at - (DENSE_RANK() OVER (PARTITION BY user_id ORDER BY visited_at))::int s
          FROM user_visits
      ), visits AS (
        SELECT user_id
             , MIN(visited_at) "start"
             , DENSE_RANK() OVER (PARTITION BY user_id ORDER BY s) "rank"
          FROM consecutive_visits
      GROUP BY user_id, s
        HAVING COUNT(*) >= #{days}
      )
      SELECT user_id
           , "start" + interval '#{days} days' "granted_at"
        FROM visits
       WHERE "rank" = 1
每日运行撤销查询
查询目标帖子
触发器 每日更新

:3rd_place_medal: 第一个表情符号

没有 SQL 查询——当符合条件的帖子通过 CookedPostProcessor#grant_badges 处理时,该徽章会立即授予。

标准: 处理后的帖子必须包含至少一个 img.emoji 元素,且该元素不在 aside.quote 块内。换句话说,直接在帖子正文中输入的表情符号有效;仅出现在引用段落中的表情符号无效。

每日运行撤销查询
查询目标帖子 :white_check_mark:
触发器 帖子处理(CookedPostProcessor)

:3rd_place_medal: 第一个标记

SELECT pa1.user_id, pa1.created_at granted_at, pa1.post_id
    FROM (
      SELECT pa.user_id, MIN(pa.id) id
      FROM post_actions pa
      JOIN badge_posts p on p.id = pa.post_id
      WHERE post_action_type_id IN (
        SELECT f.id
        FROM flags f
        WHERE name != 'like'
        AND score_type IS FALSE
        AND require_message IS FALSE
      )
      AND (:backfill OR pa.post_id IN (:post_ids))
      GROUP BY pa.user_id
    ) x
    JOIN post_actions pa1 on pa1.id = x.id
每日运行撤销查询
查询目标帖子 :white_check_mark:
触发器 当用户对帖子采取行动时

:3rd_place_medal: 第一个点赞

SELECT pa1.user_id, pa1.created_at granted_at, pa1.post_id
    FROM (
      SELECT pa.user_id, MIN(pa.id) id
      FROM post_actions pa
      JOIN badge_posts p on p.id = pa.post_id
      WHERE post_action_type_id = 2 AND
        (:backfill OR pa.post_id IN (:post_ids) )
      GROUP BY pa.user_id
    ) x
    JOIN post_actions pa1 on pa1.id = x.id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户对帖子采取行动时

:3rd_place_medal: 第一个链接

SELECT l.user_id, l.post_id, l.created_at granted_at
    FROM
    (
      SELECT MIN(l1.id) id
      FROM topic_links l1
      JOIN badge_posts p1 ON p1.id = l1.post_id
      JOIN badge_posts p2 ON p2.id = l1.link_post_id
      WHERE NOT reflection AND p1.topic_id <> p2.topic_id AND not quote AND
        (:backfill OR ( p1.id in (:post_ids) ))
      GROUP BY l1.user_id
    ) ids
    JOIN topic_links l ON l.id = ids.id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户编辑或创建帖子时

:3rd_place_medal: 第一个提及

SELECT acting_user_id AS user_id, MIN(target_post_id) AS post_id, MIN(p.created_at) AS granted_at
    FROM user_actions
    JOIN posts p ON p.id = target_post_id
    JOIN topics t ON t.id = topic_id
    JOIN categories c on c.id = category_id
    WHERE action_type = 7
      AND NOT read_restricted
      AND p.deleted_at IS  NULL
      AND t.deleted_at IS  NULL
      AND t.visible
      AND t.archetype <> 'private_message'
      AND (:backfill OR p.id IN (:post_ids))
    GROUP BY acting_user_id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户编辑或创建帖子时

:3rd_place_medal: 第一个预览框

没有 SQL 查询。在帖子处理期间通过 CookedPostProcessor#grant_badges 授予。

标准: 处理后的帖子必须生成至少一个预览框(onebox)——即当独立一行的裸 URL 解析为可嵌入资源时生成的丰富链接预览。

每日运行撤销查询
查询目标帖子 :white_check_mark:
触发器 帖子处理(CookedPostProcessor

:3rd_place_medal: 第一个引用

SELECT ids.user_id, q.post_id, p3.created_at granted_at
    FROM
    (
      SELECT p1.user_id, MIN(q1.id) id
      FROM quoted_posts q1
      JOIN badge_posts p1 ON p1.id = q1.post_id
      JOIN badge_posts p2 ON p2.id = q1.quoted_post_id
      WHERE (:backfill OR ( p1.id IN (:post_ids) ))
      GROUP BY p1.user_id
    ) ids
    JOIN quoted_posts q ON q.id = ids.id
    JOIN badge_posts p3 ON q.post_id = p3.id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户编辑或创建帖子时

:3rd_place_medal: 第一个邮件回复

没有 SQL 查询。在帖子处理期间通过 CookedPostProcessor#grant_badges 授予。

标准: post.is_reply_by_email? 必须为 true——即该帖子是通过回复 Discourse 通知邮件提交的,而不是通过 Web 界面。需要网站上启用了接收邮件回复功能。

每日运行撤销查询
查询目标帖子 :white_check_mark:
触发器 帖子处理(CookedPostProcessor

原始社区建议 'Reply by email' badge - #3 by lrossouw

:3rd_place_medal: 第一个分享

SELECT views.user_id, i2.post_id, i2.created_at granted_at
    FROM
    (
      SELECT i.user_id, MIN(i.id) i_id
      FROM incoming_links i
      JOIN badge_posts p on p.id = i.post_id
      JOIN users u on u.id = i.user_id
      GROUP BY i.user_id
    ) as views
    JOIN incoming_links i2 ON i2.id = views.i_id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 每日更新

:3rd_place_medal: 月度新用户

没有针对该徽章注册的 SQL 查询。由每日计划任务Jobs::GrantNewUserOfTheMonthBadges)授予。该任务每天运行,但仅奖励上一个自然月的用户,且每月仅授予一次。

资格: 候选人必须在上一个自然月创建账户,处于活跃状态且非预发布状态,不是管理员或版主,且未被暂停。他们还必须在至少 2 个不同的主题中发帖,总发帖数至少 2 条,并获得至少 2 个点赞

评分: 候选人根据加权点赞分数进行排名。每个获得的点赞会根据给予者的信任等级进行加权:

点赞者 权重
管理员或版主 3.0
信任等级 4 2.0
信任等级 3 1.5
信任等级 2 1.0
信任等级 1 0.25
信任等级 0 0.1

最终得分为 SUM(加权点赞) / (5 + 发帖数)——除以发帖数可以削弱高产发帖者的优势。每月最多 2 名用户可获得该徽章。每位获奖者还会收到一条系统消息。

每日运行撤销查询
查询目标帖子
触发器 每日计划任务(奖励上一个自然月)

:3rd_place_medal: 优质回复(帖子的点赞数)

:3rd_place_medal: 优质回复、:2nd_place_medal: 良好回复 和 :1st_place_medal: 精彩回复 徽章都遵循相同的模式,但 p.like_count 的阈值不同。

SELECT p.user_id, p.id post_id, CURRENT_TIMESTAMP granted_at
      FROM badge_posts p
      WHERE p.post_number > 1 AND p.like_count >= #{count.to_i} AND
        (:backfill OR p.id IN (:post_ids) )
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户对帖子采取行动时

:3rd_place_medal: 优质分享(链接分享)

:3rd_place_medal: 优质分享、:2nd_place_medal: 良好分享 和 :1st_place_medal: 精彩分享 徽章都遵循相同的模式,但 HAVING COUNT(*) 的阈值不同。

SELECT views.user_id, i2.post_id, CURRENT_TIMESTAMP granted_at
      FROM
      (
        SELECT i.user_id, MIN(i.id) i_id
        FROM incoming_links i
        JOIN badge_posts p on p.id = i.post_id
        JOIN users u on u.id = i.user_id
        GROUP BY i.user_id,i.post_id
        HAVING COUNT(DISTINCT(i.ip_address, i.current_user_id)) >= #{count}
      ) as views
      JOIN incoming_links i2 ON i2.id = views.i_id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 每日更新

:3rd_place_medal: 优质主题(主题的点赞数)

:3rd_place_medal: 优质主题、:2nd_place_medal: 良好主题 和 :1st_place_medal: 精彩主题 徽章都遵循相同的模式,但 p.like_count 的阈值不同。

SELECT p.user_id, p.id post_id, CURRENT_TIMESTAMP granted_at
      FROM badge_posts p
      WHERE p.post_number = 1 AND p.like_count >= #{count.to_i} AND
        (:backfill OR p.id IN (:post_ids) )
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户对帖子采取行动时

:3rd_place_medal: 出于爱(单日最多点赞)

:3rd_place_medal: 出于爱、:2nd_place_medal: 更高之爱 和 :1st_place_medal: 疯狂之爱 徽章都遵循相同的模式,但 HAVING COUNT(*) 的阈值不同。

SELECT gdl.user_id, CURRENT_TIMESTAMP AS granted_at
      FROM given_daily_likes AS gdl
      WHERE gdl.limit_reached
        AND (:backfill OR gdl.user_id IN (:user_ids))
      GROUP BY gdl.user_id
      HAVING COUNT(*) >= #{count}
每日运行撤销查询
查询目标帖子
触发器 每日更新

:3rd_place_medal: 热门链接(链接点击)

:3rd_place_medal: 热门链接、:2nd_place_medal: 热点链接 和 :1st_place_medal: 著名链接 都遵循相同的模式,但 tl.clicks 的阈值不同。

SELECT tl.user_id, post_id, CURRENT_TIMESTAMP granted_at
        FROM topic_links tl
        JOIN badge_posts p ON p.id = post_id
       WHERE NOT tl.internal
         AND tl.clicks >= #{count}
      GROUP BY tl.user_id, tl.post_id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 每日更新

:3rd_place_medal: 推广者(邀请)

:3rd_place_medal: 推广者、:2nd_place_medal: 活动家 和 :1st_place_medal: 冠军 徽章都遵循相同的模式,但被邀请者所需的信任等级值不同,且 HAVING COUNT(*) 的阈值也不同。

SELECT u.id user_id, CURRENT_TIMESTAMP granted_at
      FROM users u
      WHERE u.id IN (
        SELECT invited_by_id
        FROM invites i
        JOIN invited_users iu ON iu.invite_id = i.id
        JOIN users u2 ON u2.id = iu.user_id
        WHERE i.deleted_at IS NULL
        AND i.invited_by_id <> u2.id
        AND u2.active
        AND u2.trust_level >= #{trust_level.to_i}
        AND u2.silenced_till IS NULL
        GROUP BY invited_by_id
        HAVING COUNT(*) >= #{count.to_i}
      ) AND u.active AND u.silenced_till IS NULL AND u.id > 0 AND
      (:backfill OR u.id IN (:user_ids) )
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 每日更新

:3rd_place_medal: 阅读指南

 SELECT user_id, read_faq granted_at
    FROM user_stats
    WHERE read_faq IS NOT NULL AND (user_id IN (:user_ids) OR :backfill)
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 当用户被编辑或创建时

:3rd_place_medal: 读者

SELECT id user_id, CURRENT_TIMESTAMP granted_at
    FROM users
    WHERE id IN
    (
      SELECT pt.user_id
      FROM post_timings pt
      JOIN badge_posts b ON b.post_number = pt.post_number AND
                            b.topic_id = pt.topic_id
      JOIN topics t ON t.id = pt.topic_id
      LEFT JOIN user_badges ub ON ub.badge_id = 17 AND ub.user_id = pt.user_id
      WHERE ub.id IS NULL AND t.posts_count > 100
      GROUP BY pt.user_id, pt.topic_id, t.posts_count
      HAVING COUNT(*) >= t.posts_count
每日运行撤销查询
查询目标帖子
触发器

:3rd_place_medal: 谢谢(给予的点赞 + 收到的点赞)

:3rd_place_medal: 谢谢、:2nd_place_medal: 回馈 和 :1st_place_medal: 共情 徽章都遵循相同的模式,但 us.likes_givenHAVING COUNT(*) 的值不同。

SELECT us.user_id, CURRENT_TIMESTAMP granted_at
      FROM user_stats AS us
      INNER JOIN posts AS p ON p.user_id = us.user_id
      WHERE p.like_count > 0
        AND us.likes_given >= #{likes_given}
        AND (:backfill OR us.user_id IN (:user_ids))
      GROUP BY us.user_id, us.likes_given
      HAVING COUNT(*) > #{likes_received}
每日运行撤销查询
查询目标帖子
触发器 每日更新

:3rd_place_medal: 欢迎

SELECT p.user_id, MIN(post_id) post_id, MIN(pa.created_at) granted_at
    FROM post_actions pa
    JOIN badge_posts p on p.id = pa.post_id
    WHERE post_action_type_id = 2 AND
        (:backfill OR pa.post_id IN (:post_ids) )
    GROUP BY p.user_id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户对帖子采取行动时

:3rd_place_medal: 维基编辑者

SELECT pr2.user_id, pr2.post_id, pr2.created_at granted_at
    FROM
    (
      SELECT MIN(pr.id) id
      FROM post_revisions pr
      JOIN badge_posts p on p.id = pr.post_id
      WHERE p.wiki
          AND NOT pr.hidden
          AND (:backfill OR p.id IN (:post_ids))
      GROUP BY pr.user_id
    ) as X
    JOIN post_revisions pr2 ON pr2.id = X.id
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户编辑或创建帖子时

Discourse 反应

:3rd_place_medal: 第一个反应

SELECT user_id, created_at AS granted_at, post_id
  FROM (
           SELECT ru.post_id, ru.user_id, ru.created_at,
                  ROW_NUMBER() OVER (PARTITION BY ru.user_id ORDER BY ru.created_at) AS row_number
           FROM discourse_reactions_reaction_users ru
                JOIN badge_posts p ON ru.post_id = p.id
           WHERE :backfill
              OR ru.post_id IN (:post_ids)
       ) x
  WHERE row_number = 1
每日运行撤销查询 :white_check_mark:
查询目标帖子 :white_check_mark:
触发器 当用户编辑或创建帖子时

Discourse 已解决

:3rd_place_medal: 已解决!

 SELECT post_id, user_id, created_at AS granted_at
  FROM (
           SELECT p.id AS post_id, p.user_id, dsst.created_at,
              ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY dsst.created_at) AS row_number
           FROM discourse_solved_solved_topics dsst
              JOIN badge_posts p ON dsst.answer_post_id = p.id
              JOIN topics t ON p.topic_id = t.id
           WHERE p.user_id <> t.user_id -- 忽略由原作者解决的主题
              AND (:backfill OR p.id IN (:post_ids))
       ) x
  WHERE row_number = 1
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 当用户编辑或创建帖子时

:2nd_place_medal: 指导顾问

:2nd_place_medal: 指导顾问、:1st_place_medal: 万事通 和 :1st_place_medal: 解决方案机构 徽章都遵循相同的模式,但 HAVING COUNT (*) >= 的阈值不同:

SELECT p.user_id, MAX(pcf.created_at) AS granted_at
   FROM post_custom_fields pcf
        JOIN badge_posts p ON pcf.post_id = p.id
        JOIN topics t ON p.topic_id = t.id
   WHERE pcf.name = 'is_accepted_answer'
     AND p.user_id <> t.user_id -- 忽略由原作者解决的主题
     AND (:backfill OR p.id IN (:post_ids))
   GROUP BY p.user_id
   HAVING COUNT(*) >= #{min_count}
每日运行撤销查询 :white_check_mark:
查询目标帖子
触发器 当用户编辑或创建帖子时

Discourse Github

我无法阅读这些。:upside_down:

来源:

太棒了 @JammyDodger 感谢你分享这个有用的主题! :slight_smile: