更改站点 URL 后运行 remap 时出错

我更改了 Discourse 站点的 URL,并正在按照 Change the domain name or rename your Discourse 中的说明进行操作。在尝试运行 remap 时,我反复遇到以下错误。它一直提示我重新运行脚本,但每次都会出现相同的错误。[1]

我不确定下一步该怎么做,如果能得到指导将不胜感激。提前感谢!:seedling:

root@digitallysovereign:/var/discourse# ./launcher enter app
x86_64 arch detected.
root@digitallysovereign-app:/var/www/discourse# discourse remap discourse.tobiaseigen.org digitallysovereign.org
Rewriting all occurrences of discourse.tobiaseigen.org to digitallysovereign.org
WILL RUN ON 'default' DB
THIS TASK WILL REWRITE DATA, ARE YOU SURE (type YES): YES

Remapping tables on default...

ai_api_audit_logs=919
ai_secrets=1
backup_metadata=1
browser_pageview_events=3664
Error: ERROR:  duplicate key value violates unique constraint "idx_bprd_rollups_date_referrer_unique"
DETAIL:  Key (date, normalized_referrer)=(2026-07-01, digitallysovereign.org) already exists.
The remap has only been partially applied due to the error above. Please re-run the script again.
root@digitallysovereign-app:/var/www/discourse# discourse remap discourse.tobiaseigen.org digitallysovereign.org
Rewriting all occurrences of discourse.tobiaseigen.org to digitallysovereign.org
WILL RUN ON 'default' DB
THIS TASK WILL REWRITE DATA, ARE YOU SURE (type YES): YES

Remapping tables on default...

Error: ERROR:  duplicate key value violates unique constraint "idx_bprd_rollups_date_referrer_unique"
DETAIL:  Key (date, normalized_referrer)=(2026-07-01, digitallysovereign.org) already exists.
The remap has only been partially applied due to the error above. Please re-run the script again.
root@digitallysovereign-app:/var/www/discourse# discourse remap discourse.tobiaseigen.org digitallysovereign.org
Rewriting all occurrences of discourse.tobiaseigen.org to digitallysovereign.org
WILL RUN ON 'default' DB
THIS TASK WILL REWRITE DATA, ARE YOU SURE (type YES): YES

Remapping tables on default...

Error: ERROR:  duplicate key value violates unique constraint "idx_bprd_rollups_date_referrer_unique"
DETAIL:  Key (date, normalized_referrer)=(2026-07-01, digitallysovereign.org) already exists.
The remap has only been partially applied due to the error above. Please re-run the script again.

  1. 我知道“疯狂”的定义就是反复做同一件事却期待不同的结果!:rofl: ↩︎

看起来是 PostgreSQL 分析表中的约束冲突。你的数据库中已经包含了特定日期下新域名的记录,因此重映射工具可能正在创建重复项,而 PostgreSQL 拒绝了这些记录。

我建议你尝试在特定表中仅删除那些新域名已有数据的日期对应的旧域名记录,以保留历史数据并解除重映射工具的阻塞。不过,请先进行安全备份。

尝试以下操作:

cd /var/discourse
./launcher enter app
# 创建安全备份
discourse backup
# 进入数据库控制台
sudo -u postgres psql discourse
/* 查找与该索引关联的确切表名 */
SELECT tablename 
FROM pg_indexes 
WHERE indexname = 'idx_bprd_rollups_date_referrer_unique';

假设上述查询返回 browser_pageview_rollup_details,则在下一个查询中使用该表名

/* 删除冲突的分析记录 */
DELETE FROM browser_pageview_rollup_details 
WHERE normalized_referrer = 'discourse.tobiaseigen.org' 
AND date IN (
    SELECT date 
    FROM browser_pageview_rollup_details 
    WHERE normalized_referrer = 'digitallysovereign.org'
);

/* 退出 PostgreSQL */
\q

然后再次运行重映射工具

discourse remap discourse.tobiaseigen.org digitallysovereign.org

然后使用 rebake_match rake 任务代替完全重烘焙

# 仅重烘焙包含新域名字符串的帖子
rake posts:rebake_match["digitallysovereign.org"]

我认为Lilly的想法应该可行。

我的做法是备份数据库,更改URL,然后进行恢复,让Discourse的重映射工具来完成工作。这段代码由Discourse托管服务使用,如果出现问题,会有人注意到并修复。:slight_smile:

不过,确实,那些引用链接引发了各种问题。

谢谢,Lilly!

discourse db 对我来说不起作用——我使用的是 sudo -u postgres psql discourse

第一个查询返回的表实际上是 browser_pageview_referrer_daily_rollups,所以我第二个查询也用了这个表。

现在我遇到了一个不同的错误。再次运行第二个查询时,它没有删除任何内容。

错误:ERROR:  重复的键值违反了唯一约束 "idx_bprd_rollups_date_referrer_unique"
详细信息:  键 (date, normalized_referrer)=(2026-06-30, digitallysovereign.org/c/members/32) 已存在。
由于上述错误,重映射仅部分应用。请重新运行脚本。

好吧,我想最初的查询使用了精确匹配,所以它遗漏了所有带有路径的行。我想试试这个 SQL 查询(我无法真正测试这些,因为我没有在我的域名服务器上更改域名的需求)。

DELETE FROM browser_pageview_referrer_daily_rollups old_table
WHERE old_table.normalized_referrer LIKE '%discourse.tobiaseigen.org%'
AND EXISTS (
    SELECT 1 
    FROM browser_pageview_referrer_daily_rollups new_table
    WHERE new_table.date = old_table.date
    AND new_table.normalized_referrer = REPLACE(old_table.normalized_referrer, 'discourse.tobiaseigen.org', 'digitallysovereign.org')
);
\q

如果这能无错误地运行,那么运行我之前发布的重映射工具和 rebake rake 任务。

我确实在几个月前做过一次论坛迁移到新服务器和新域名,但重映射工具对我来说第一次就完美运行了。

再次感谢,Lilly!你真是棒极了。

我似乎正在一点点地处理数据库。24 条记录已被删除!现在我已经到了 unique_post_links

root@digitallysovereign-app:/var/www/discourse# discourse remap discourse.tobiaseigen.org digitallysovereign.org
Rewriting all occurrences of discourse.tobiaseigen.org to digitallysovereign.org
WILL RUN ON 'default' DB
THIS TASK WILL REWRITE DATA, ARE YOU SURE (type YES): yes

Remapping tables on default...

browser_pageview_referrer_daily_rollups=1466
categories=2
chat_message_links=4
chat_message_search_data=4
chat_messages=5
discourse_activity_pub_collections=1
discourse_activity_pub_objects=1
drafts=4
email_logs=797
group_histories=2
groups=2
incoming_emails=21
moved_posts=2
notifications=10
post_localizations=51
post_revisions=31
post_search_data=226
posts=774
site_settings=1
stylesheet_cache=1168
Error: ERROR:  duplicate key value violates unique constraint "unique_post_links"
DETAIL:  Key (topic_id, post_id, url)=(581, 3696, https://digitallysovereign.org) already exists.
The remap has only been partially applied due to the error above. Please re-run the script again.

好的,让我们用同样的逻辑,但先验证一下:

SELECT tablename 
FROM pg_indexes 
WHERE indexname = 'unique_post_links';

应该会返回 topic_links 吧?因此,接下来的逻辑步骤是:

DELETE FROM topic_links old_link
WHERE old_link.url LIKE '%discourse.tobiaseigen.org%'
AND EXISTS (
    SELECT 1 
    FROM topic_links new_link
    WHERE new_link.topic_id = old_link.topic_id
    AND new_link.post_id = old_link.post_id
    AND new_link.url = REPLACE(old_link.url, 'discourse.tobiaseigen.org', 'digitallysovereign.org')
);
\q

我认为这已经接近数据库结构的末尾了,所以这很可能是运行我之前发布的 remap 和 rake 任务之前的最后一道障碍(我希望如此)…

全部完成!:rocket:

root@digitallysovereign-app:/var/www/discourse# discourse remap discourse.tobiaseigen.org digitallysovereign.org
正在将所有 discourse.tobiaseigen.org 重写为 digitallysovereign.org
将在 'default' 数据库上运行
此任务将重写数据,确定吗(输入 YES):yes

正在 default 数据库上重映射表...

topic_links=1449
topic_search_data=11
topics=11
user_auth_token_logs=5
user_histories=131
完成

我想你应该把其中一个标记为解决方案 :wink:

没问题!

能给我解释一下 discourse db 是什么,以及为什么你能用它而我却不行吗?这似乎比 sudo -u postgres psql discourse 更容易记住!

我只是记错了,因为我在容器里很少执行这种 SQL。我确实以为那是正确的命令。我想是因为 Discourse 内置了像 discourse backupdiscourse remap 这样的命令。

这其实是个变相的功能请求!

:disguised_face:

好吧,纯粹为了试试,我为 script/discourse 文件快速提交了一个 PR,以使用 discourse db。不太确定团队是否想添加这个功能,但它确实让在容器内进入 sql 控制台变得更容易。