仪表盘报告 - 管理员活动

这是Moderator Activity的仪表板报告的SQL版本。

本报告提供了在指定时间范围内,在Discourse站点上版主执行的活动的全面概述。报告结合了版主活动的多个方面:在平台上的花费时间、审查的标记数量、创建的帖子、创建的个人消息(PM)、创建的主题以及进行的帖子修订。

此仪表板报告是管理员衡量其版主团队的有效性和参与度的宝贵工具,提供了对其活动和贡献的详细了解。报告提供的见解可以为版主培训、认可和招聘的决策提供信息,并确保版主团队均衡且有效地维护社区标准。

--[params]
-- date :start_date = 2023-12-01
-- date :end_date = 2024-12-01
-- boolean :include_admins = false


WITH mods AS (
    SELECT
        id AS user_id,
        username_lower AS username,
        uploaded_avatar_id
    FROM users u
    WHERE ((u.moderator = true) OR (:include_admins AND u.admin = true))
    AND u.id > 0

),

time_read AS (
    SELECT SUM(uv.time_read) AS time_read,
        uv.user_id
    FROM mods m
    JOIN user_visits uv ON m.user_id = uv.user_id
    WHERE uv.visited_at >= :start_date
        AND uv.visited_at <= :end_date
    GROUP BY uv.user_id
),

flag_count AS (
    WITH period_actions AS (
        SELECT agreed_by_id,
        disagreed_by_id
        FROM post_actions
        WHERE post_action_type_id IN (3,4,8,6,7)
        AND created_at >= :start_date
        AND created_at <= :end_date
    ),

agreed_flags AS (
        SELECT pa.agreed_by_id AS user_id,
        COUNT(*) AS flag_count
        FROM mods m
        JOIN period_actions pa
        ON pa.agreed_by_id = m.user_id
        GROUP BY agreed_by_id
    ),

disagreed_flags AS (
        SELECT pa.disagreed_by_id AS user_id,
        COUNT(*) AS flag_count
        FROM mods m
        JOIN period_actions pa
        ON pa.disagreed_by_id = m.user_id
        GROUP BY disagreed_by_id
    )
    SELECT
    COALESCE(af.user_id, df.user_id) AS user_id,
    COALESCE(af.flag_count, 0) + COALESCE(df.flag_count, 0) AS flag_count
    FROM agreed_flags af
    FULL OUTER JOIN disagreed_flags df
    ON df.user_id = af.user_id
      ),

revision_count AS (
      SELECT pr.user_id,
      COUNT(*) AS revision_count
      FROM mods m
      JOIN post_revisions pr
      ON pr.user_id = m.user_id
      JOIN posts p
      ON p.id = pr.post_id
      WHERE pr.created_at >= :start_date
      AND pr.created_at <= :end_date
      AND p.user_id <> pr.user_id
      GROUP BY pr.user_id
),

topic_count AS (
      SELECT t.user_id,
        COUNT(*) AS topic_count
      FROM mods m
      JOIN topics t ON t.user_id = m.user_id
      WHERE t.archetype = 'regular'
          AND t.created_at >= :start_date
          AND t.created_at <= :end_date
      GROUP BY t.user_id
),

post_count AS (
      SELECT p.user_id,
         COUNT(*) AS post_count
      FROM mods m
      JOIN posts p ON p.user_id = m.user_id
      JOIN topics t ON t.id = p.topic_id
      WHERE t.archetype = 'regular'
          AND p.created_at >= :start_date
          AND p.created_at <= :end_date
      GROUP BY p.user_id
),

pm_count AS (
      SELECT p.user_id,
        COUNT(*) AS pm_count
      FROM mods m
      JOIN posts p ON p.user_id = m.user_id
      JOIN topics t ON t.id = p.topic_id
      WHERE t.archetype = 'private_message'
          AND p.created_at >= :start_date
          AND p.created_at <= :end_date
      GROUP BY p.user_id
      )

SELECT
    m.user_id,
    m.username,
    fc.flag_count as flags_reviewed,
    ROUND(((tr.time_read) / 3600.00),2) as time_reading_hours,
    tc.topic_count as topics_created,
    pmc.pm_count as PMs_created,
    pc.post_count as posts_created,
    rc.revision_count as revisions
FROM mods m
LEFT JOIN time_read tr ON tr.user_id = m.user_id
LEFT JOIN flag_count fc ON fc.user_id = m.user_id
LEFT JOIN revision_count rc ON rc.user_id = m.user_id
LEFT JOIN topic_count tc ON tc.user_id = m.user_id
LEFT JOIN post_count pc ON pc.user_id = m.user_id
LEFT JOIN pm_count pmc ON pmc.user_id = m.user_id
ORDER BY m.username ASC

参数

  • :start_date:end_date - 这些参数定义了报告的日期范围。两个日期参数都接受 YYYY-MM-DD 格式的日期。
  • :include_admins - 此参数决定是否在报告中包含管理员以及版主。

SQL 查询说明

报告使用通用表表达式(CTE)进行结构化,将数据处理划分为可管理和逻辑的部分。以下是每个CTE的功能:

  1. mods:识别所有具有版主身份或管理员身份(如果通过 :include_admins 参数包含)的用户。它仅选择相关的用户列以供进一步查询。
  2. time_read:计算在提供的开始和结束日期之间,每位版主在平台上阅读内容所花费的总时间(以秒为单位)。
  3. flag_count:计算在指定期间内版主同意或不同意的标记数量。它考虑了由各自的帖子操作类型ID表示的多个标记类型。
  4. revision_count:计算在给定时间范围内,版主对其他用户帖子进行的修订数量。
  5. topic_count:计算版主创建的常规主题的数量。
  6. post_count:计算版主在常规主题中创建的帖子的数量。
  7. pm_count:计算版主发起的私人消息的数量。

在CTE中收集数据后,主查询根据用户ID将它们连接起来,并编译最终报告,显示每位版主的用户名、花费的阅读时间总数(转换为小时)、审查的标记数量、创建的主题、创建的个人消息、创建的帖子以及进行的修订。结果按版主的用户名字母顺序排序。

示例结果

user username flags_reviewed time_reading_hours topics_created pms_created posts_created revisions
1 moderator1 NULL 36.11 NULL 344 8 15
2 moderator2 46 104.52 2 271 466 363
3 moderator3 NULL 72.15 NULL 418 64 16
7 个赞

您好 @SaraDev

这真的很有用。是否可以为版主活动报告添加“已批准帖子”和“已拒绝帖子”列?

谢谢,
T_Disco

3 个赞

你好 @T_Disco,

是的,要将“已批准帖子”和“已拒绝帖子”的结果添加到版主活动报告中,我们可以利用 reviewablesreviewable_scores 表。具体来说,reviewable_scores 中的 status 字段可用于确定帖子是被批准(status = 1)还是被拒绝(status = 2)。

添加到报告中的效果如下:

包含已批准帖子和已拒绝帖子的版主活动

-- [params]
-- date :start_date = 2023-12-01
-- date :end_date = 2024-12-01
-- boolean :include_admins = false

WITH mods AS (
    SELECT
        id AS user_id,
        username_lower AS username,
        uploaded_avatar_id
    FROM users u
    WHERE ((u.moderator = true) OR (:include_admins AND u.admin = true))
    AND u.id > 0
),

time_read AS (
    SELECT SUM(uv.time_read) AS time_read,
        uv.user_id
    FROM mods m
    JOIN user_visits uv ON m.user_id = uv.user_id
    WHERE uv.visited_at >= :start_date
        AND uv.visited_at <= :end_date
    GROUP BY uv.user_id
),
      
flag_count AS (
    WITH period_actions AS (
        SELECT agreed_by_id,
        disagreed_by_id
        FROM post_actions
        WHERE post_action_type_id IN (3,4,8,6,7)
        AND created_at >= :start_date
        AND created_at <= :end_date
    ),

agreed_flags AS (
        SELECT pa.agreed_by_id AS user_id,
        COUNT(*) AS flag_count
        FROM mods m
        JOIN period_actions pa
        ON pa.agreed_by_id = m.user_id
        GROUP BY agreed_by_id
    ),

disagreed_flags AS (
        SELECT pa.disagreed_by_id AS user_id,
        COUNT(*) AS flag_count
        FROM mods m
        JOIN period_actions pa
        ON pa.disagreed_by_id = m.user_id
        GROUP BY disagreed_by_id
    )
    SELECT
    COALESCE(af.user_id, df.user_id) AS user_id,
    COALESCE(af.flag_count, 0) + COALESCE(df.flag_count, 0) AS flag_count
    FROM agreed_flags af
    FULL OUTER JOIN disagreed_flags df
    ON df.user_id = af.user_id
      ),
      
revision_count AS (
      SELECT pr.user_id,
      COUNT(*) AS revision_count
      FROM mods m
      JOIN post_revisions pr
      ON pr.user_id = m.user_id
      JOIN posts p
      ON p.id = pr.post_id
      WHERE pr.created_at >= :start_date
      AND pr.created_at <= :end_date
      AND p.user_id <> pr.user_id
      GROUP BY pr.user_id
),
      
topic_count AS (
      SELECT t.user_id,
        COUNT(*) AS topic_count
      FROM mods m
      JOIN topics t ON t.user_id = m.user_id
      WHERE t.archetype = 'regular'
          AND t.created_at >= :start_date
          AND t.created_at <= :end_date
      GROUP BY t.user_id
),
      
post_count AS (
      SELECT p.user_id,
         COUNT(*) AS post_count
      FROM mods m
      JOIN posts p ON p.user_id = m.user_id
      JOIN topics t ON t.id = p.topic_id
      WHERE t.archetype = 'regular'
          AND p.created_at >= :start_date
          AND p.created_at <= :end_date
      GROUP BY p.user_id
),
      
pm_count AS (
      SELECT p.user_id,
        COUNT(*) AS pm_count
      FROM mods m
      JOIN posts p ON p.user_id = m.user_id
      JOIN topics t ON t.id = p.topic_id
      WHERE t.archetype = 'private_message'
          AND p.created_at >= :start_date
          AND p.created_at <= :end_date
      GROUP BY p.user_id
),

reviewable_actions AS (
    SELECT
        rs.reviewed_by_id AS user_id,
        SUM(CASE WHEN rs.status = 1 THEN 1 ELSE 0 END) AS posts_approved,
        SUM(CASE WHEN rs.status = 2 THEN 1 ELSE 0 END) AS posts_rejected
    FROM mods m
    JOIN reviewable_scores rs ON rs.reviewed_by_id = m.user_id
    JOIN reviewables r ON r.id = rs.reviewable_id
    WHERE rs.reviewed_at >= :start_date
      AND rs.reviewed_at <= :end_date
    GROUP BY rs.reviewed_by_id
)

SELECT
    m.user_id,
    m.username,
    fc.flag_count as flags_reviewed,
    ROUND(((tr.time_read) / 3600.00),2) as time_reading_hours,
    tc.topic_count as topics_created,
    pmc.pm_count as PMs_created,
    pc.post_count as posts_created,
    rc.revision_count as revisions,
    ra.posts_approved,
    ra.posts_rejected
FROM mods m
LEFT JOIN time_read tr ON tr.user_id = m.user_id
LEFT JOIN flag_count fc ON fc.user_id = m.user_id
LEFT JOIN revision_count rc ON rc.user_id = m.user_id
LEFT JOIN topic_count tc ON tc.user_id = m.user_id
LEFT JOIN post_count pc ON pc.user_id = m.user_id
LEFT JOIN pm_count pmc ON pmc.user_id = m.user_id
LEFT JOIN reviewable_actions ra ON ra.user_id = m.user_id
ORDER BY m.username ASC

此报告的结果将如下所示:

user username flags_reviewed time_reading_hours topics_created pms_created posts_created revisions posts_approved posts_rejected
1 moderator1 NULL 36.11 NULL 344 8 15 10 5
2 moderator2 46 104.52 2 271 466 363 7 3
3 moderator3 NULL 72.15 NULL 418 64 16 NULL NULL
1 个赞

太棒了,谢谢你 @SaraDev

这些列是否会在某个时候添加到 /admin/dashboard/moderation 选项卡上的版主活动报告中?

再次感谢 :slight_smile:
T_Disco

1 个赞

@SaraDev
是否可以查询在给定时间段内执行的主题合并数量?

2 个赞

我们目前没有计划将这些列添加到仪表板版本的报告中,但我可以与我们的团队讨论一下,看看将来是否可以进行一些改进。:slightly_smiling_face:

是的,要创建一个显示帖子被移动到其他主题的时间的查询,您可以筛选 posts 表中 action_code 指示移动且包含 split_topic 条目的记录。

例如:

单个帖子移动操作

SELECT
    id AS post_id,
    user_id,
    topic_id,
    post_number,
    created_at::date,
    updated_at::date,
    action_code
FROM
    posts
WHERE
    action_code = 'split_topic'
ORDER BY
    created_at DESC

将显示类似以下的结果:

帖子 用户 主题 帖子编号 创建时间 更新时间 操作代码
一个帖子被合并到一个现有主题:: [合并主题标题] 用户名 原始主题标题 3 2024-10-30 2024-10-30 split_topic
2个帖子被合并到一个现有主题:: [合并主题标题] 用户名 原始主题标题 5 2024-10-30 2024-10-30 split_topic
一个帖子被分割到一个新主题: [分割主题标题] 用户名 原始主题标题 2 2024-10-30 2024-10-30 split_topic

如果您想显示网站上每个用户的帖子移动总数,并添加几个参数按日期过滤移动操作,您还可以使用类似以下的查询:

每个用户的帖子移动操作数量

-- [params]
-- date :start_date
-- date :end_date

SELECT
    user_id,
    COUNT(*) AS move_count
FROM
    posts
WHERE
    action_code = 'split_topic'
    AND created_at BETWEEN :start_date AND :end_date
GROUP BY
    user_id
ORDER BY
    move_count DESC

其中示例结果看起来像:

用户 移动次数
用户名_1 5
用户名_2 2

请注意,在这两个查询中,将任意数量的帖子从一个主题移动到另一个主题只算作一次操作,无论移动了多少帖子。将整个主题的内容移动到另一个主题也只算作一次操作。

在“单个帖子移动操作”查询的 post 列中,可以使用文本 X posts were merged into an existing topic... 来查看每次操作移动的帖子数量,但第二个查询中没有此信息。

在“单个帖子移动操作”查询中,您还可能看到带有文本“A post was split to a new topic …”的帖子,这表示该帖子被分割成了一个新主题,而不是被移动到现有主题中,因为 Discourse 将这两种操作都视为 split_topic 操作,因为帖子正在从一个主题移动到另一个主题。

2 个赞

5 篇帖子已拆分到一个新主题:用户页面指标