帮助映射迁移前线程的插件在迁移后

您好,我和我的一群疯狂的白痴终于要将我们的 Vbulletin3 论坛迁移到 Discourse 了,我们为此编写了一个临时的脚本,终于成功地将原始数据库中的 2100 万条回复迁移到了 Discourse。

现在,我们遇到了一个问题,那就是回复中包含指向主题/回复的链接。

在我们编写的迁移脚本中,我们记录了“旧”主题和帖子的 ID 以及它们在 Discourse 中对应的 ID。

例如:

   id   | topic_id |   name    | value  |         created_at         |         updated_at
--------+----------+-----------+--------+----------------------------+----------------------------
 581727 |   581736 | import_id | 599137 | 2023-02-08 16:30:01.600759 | 2023-02-08 16:30:01.600759

我现在想到的是一个插件,它可以拦截旧论坛格式的链接,并将它们转换为指向新帖子/回复的链接。

例如,类似这样的链接:

https://oldforum.something.com/showthread.php?t=123456

将触发一个查询,使用 topics_custom_field 查找值为 123456 的条目,找到 Discourse 的 topic_id,然后使用该 ID 查询 topic_links 表,找到 url。最后在客户端(假设使用 JS 操作内容)替换帖子中的链接。

对于帖子也类似。

然而,我找不到任何关于如何开始为 Discourse 创建类似内容的好的例子。
有人能给我一些提示、例子或插件,可以做类似的事情(检查回复中的某个子字符串并替换它,查询 API?数据库?以一个值换取另一个值吗?)

谢谢

这在核心中已存在,称为永久链接 (Permalinks),现有的 VB4 导入器为此提供了代码

您应该在 permalink_normalizations 设置中输入类似 /showthread\\.php\\?(\\d*)/thread/\\1 的内容。

2 个赞

确认一下,我应该在迁移完成后运行这段逻辑,对吧?
这样就可以再次遍历所有回复并更改永久链接了。

您说的更改是什么意思?您已经有永久链接了吗?

当我们迁移回复内容时,例如:https://oldforum.something.com/showthread.php?t=123456 不知道该主题在 discourse 上的 id 是什么……是吗?

如果您使用上面的代码创建永久链接,它就会。

showthread.php?t= 是指一个主题/帖子,而不是回复。

1 个赞

我只是把那个链接当作例子 :slight_smile:

不幸的是,我们不能使用那段代码,因为导入 2000 万条帖子需要很长时间,而且批量导入根本不起作用。缺少一些部分。

这就是为什么我们不得不编写自己的迁移脚本。它可以在 6 小时内完成所有工作(pm、用户、用户组、类别、主题、回复),使用的是 4 核、8GB 内存的机器,但我们注意到缺少了永久链接 :slight_smile:

也许您可以考虑使用预固定链接 Nginx map 解决方案?Redirect vBulletin URLs to Discourse URLs

1 个赞

我们内部讨论了一下,将在所有回复迁移完成后再进行第二次处理。

谢谢你和我一起探讨想法,Richard :heart:

您的脚本是否创建了 import_ids?如果创建了,即使您没有创建 permalinks,您也可以相当快地处理它们来创建它们。

是的,Jay,我们有。

我们曾试图避免再次循环处理全部 2000 万条回复,但意识到其他解决方案(插件、nginx 重定向等)会相当复杂,或者依赖外部因素,这将是一个敷衍了事的解决方案,所以我们将再次循环处理回复并处理永久链接。这会增加迁移时间,但希望不会太多。

其他所有内容都是在“飞行中”完成的,因为我们知道“原始”内容需要转换为 html。

对于永久链接,我们无法这样做,因为如果添加了带有编辑的永久链接,它可能会引用尚未处理的主题(主题 ID 较高),并且在处理时在 topics_custom_field 表中找不到这些主题。

我不知道你如何在不先创建主题的情况下创建 topic_custom_fields。我认为你可以这样做:

TopicCustomField.each do |tcf|

并创建永久链接,但你的代码有很多我不知道的地方。

让我来澄清一下:

主题及其所有回复都按照 vbulletin 数据库中的主题 ID 从小到大的顺序导入。这也意味着我们是按时间顺序导入的。

然而,这会让人认为,如果你发现对另一个主题的引用,它总是会引用一个已经存在的主题。

但有些情况并非如此,举几个例子:

  • 分割主题,其中包含导致分割的评论。分割的主题 ID 会更大,但存在于 ID 更小的主题中。
  • 为了方便未来的读者而进行的编辑,其中旧主题的帖子会引用更新的主题。

所以,是的,虽然 topic_custom_field 是在导入过程中生成和填充的,正如在第一个主题中所解释的那样,但“即时”处理并不可靠,因为你不能确定总是能找到 ID 之间的正确对应关系。

在完成全部导入后需要进行另一次传递。

关于 TopicCustomField.each do |tcf|,我不确定 tcf 部分会做什么。Ruby 不是我学过的语言。我们的脚本是用 C# 编写的,因为大多数愿意使用它的人已经在工作中使用了 C#。

1 个赞