Crius
(Crius)
1
您好,我和我的一群疯狂的白痴终于要将我们的 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?数据库?以一个值换取另一个值吗?)
谢谢
RGJ
(Richard - Communiteq)
2
这在核心中已存在,称为永久链接 (Permalinks),现有的 VB4 导入器为此提供了代码
您应该在 permalink_normalizations 设置中输入类似 /showthread\\.php\\?(\\d*)/thread/\\1 的内容。
2 个赞
Crius
(Crius)
3
确认一下,我应该在迁移完成后运行这段逻辑,对吧?
这样就可以再次遍历所有回复并更改永久链接了。
Crius
(Crius)
5
当我们迁移回复内容时,例如:https://oldforum.something.com/showthread.php?t=123456 不知道该主题在 discourse 上的 id 是什么……是吗?
RGJ
(Richard - Communiteq)
6
如果您使用上面的代码创建永久链接,它就会。
showthread.php?t= 是指一个主题/帖子,而不是回复。
1 个赞
Crius
(Crius)
7
我只是把那个链接当作例子 
不幸的是,我们不能使用那段代码,因为导入 2000 万条帖子需要很长时间,而且批量导入根本不起作用。缺少一些部分。
这就是为什么我们不得不编写自己的迁移脚本。它可以在 6 小时内完成所有工作(pm、用户、用户组、类别、主题、回复),使用的是 4 核、8GB 内存的机器,但我们注意到缺少了永久链接 
RGJ
(Richard - Communiteq)
8
1 个赞
Crius
(Crius)
9
我们内部讨论了一下,将在所有回复迁移完成后再进行第二次处理。
谢谢你和我一起探讨想法,Richard 
pfaffman
(Jay Pfaffman)
10
您的脚本是否创建了 import_ids?如果创建了,即使您没有创建 permalinks,您也可以相当快地处理它们来创建它们。
Crius
(Crius)
11
是的,Jay,我们有。
我们曾试图避免再次循环处理全部 2000 万条回复,但意识到其他解决方案(插件、nginx 重定向等)会相当复杂,或者依赖外部因素,这将是一个敷衍了事的解决方案,所以我们将再次循环处理回复并处理永久链接。这会增加迁移时间,但希望不会太多。
其他所有内容都是在“飞行中”完成的,因为我们知道“原始”内容需要转换为 html。
对于永久链接,我们无法这样做,因为如果添加了带有编辑的永久链接,它可能会引用尚未处理的主题(主题 ID 较高),并且在处理时在 topics_custom_field 表中找不到这些主题。
pfaffman
(Jay Pfaffman)
12
我不知道你如何在不先创建主题的情况下创建 topic_custom_fields。我认为你可以这样做:
TopicCustomField.each do |tcf|
并创建永久链接,但你的代码有很多我不知道的地方。
Crius
(Crius)
13
让我来澄清一下:
主题及其所有回复都按照 vbulletin 数据库中的主题 ID 从小到大的顺序导入。这也意味着我们是按时间顺序导入的。
然而,这会让人认为,如果你发现对另一个主题的引用,它总是会引用一个已经存在的主题。
但有些情况并非如此,举几个例子:
- 分割主题,其中包含导致分割的评论。分割的主题 ID 会更大,但存在于 ID 更小的主题中。
- 为了方便未来的读者而进行的编辑,其中旧主题的帖子会引用更新的主题。
所以,是的,虽然 topic_custom_field 是在导入过程中生成和填充的,正如在第一个主题中所解释的那样,但“即时”处理并不可靠,因为你不能确定总是能找到 ID 之间的正确对应关系。
在完成全部导入后需要进行另一次传递。
关于 TopicCustomField.each do |tcf|,我不确定 tcf 部分会做什么。Ruby 不是我学过的语言。我们的脚本是用 C# 编写的,因为大多数愿意使用它的人已经在工作中使用了 C#。
1 个赞