# 徽章回填代码

**URL:** https://meta.discourse.org/t/badge-backfill-code/174120
**Category:** Feature
**Created:** [2020年十二月23日 16:32 UTC](https://meta.discourse.org/t/badge-backfill-code/174120 "2020-12-23T16:32:14Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![Ghan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ghan/32/177964_2.png) [@Ghan](https://meta.discourse.org/u/Ghan)
#### Post date: [2020年十二月23日 16:32 UTC](https://meta.discourse.org/t/badge-backfill-code/174120/1 "2020-12-23T16:32:14Z")

</div>

我正在查看这里正在进行的徽章回填过程：

> <https://github.com/discourse/discourse/blob/main/app/services/badge_granter.rb>

特别是，以下查询似乎存在一些问题（参见 [https://meta.discourse.org/t/long-running-sidekiq-jobs/173974）：](https://meta.discourse.org/t/long-running-sidekiq-jobs/173974%EF%BC%89%EF%BC%9A)

```plaintext
    sql = <<~SQL
      DELETE FROM user_badges
        WHERE id IN (
          SELECT ub.id
          FROM user_badges ub
          LEFT JOIN (
            #{badge.query}
          ) q ON q.user_id = ub.user_id
          #{post_clause}
          WHERE ub.badge_id = :id AND q.user_id IS NULL
        )
    SQL

```

该查询执行了 LEFT JOIN，因此无论是否有匹配项，都会返回 user\_badges 中的所有结果，但这一部分似乎非常令人困惑：

```plaintext
ON q.user_id = ub.user_id
...
AND q.user_id IS NULL

```

该查询在 user\_id 匹配的行上进行连接，但随后通过 WHERE 子句丢弃了这些行，使得这里的连接变得毫无意义。因此我想知道：

1. 回填函数的目的是什么？它似乎完全清除了正在处理的徽章，然后一次性重新构建所有内容。这有必要吗？

2. 针对帖子的徽章与不针对帖子的徽章在此函数方面有什么区别？使用 LEFT JOIN 时，在查找要清除以进行重建的正确 badge\_id 时，这是否甚至重要？
