大型 Drupal 论坛迁移,导入器错误和限制

哦……我从未想过在生产数据上运行导入器不止一次。非常感谢您提供的这个想法。

所以基本上,我会做一个生产 Drupal 数据库转储,然后运行一个完整的导入,无论需要多长时间,同时让 Drupal 论坛对公众开放,然后我会将 Drupal 论坛置于离线模式,再做一个数据库转储并将其加载到导入器 MySQL 实例中,然后重新运行导入器脚本?

我能看到的唯一缺点是,在初始导入到第二次导入之间的这段时间(我们称之为 3 天)内,任何 Drupal 帖子编辑或帖子_删除_或现有用户配置文件更改都不会被导入,只有在此期间内完全新用户和帖子会被导入,对吗?

没错。编辑过的数据将会丢失。另一种选择是将论坛在此期间下线。您可以提醒大家。实际上,没有人抱怨过。

1 个赞

太好了,这听起来是一个相当合理的折衷方案,可以最大限度地减少停机时间。再次感谢您的建议。

1 个赞

在我承诺进行最终的生产导入运行后,我随机检查了一些导入的论坛主题,这时我发现了一个大问题。正如这里反复出现的主题一样,这并不是 Discourse 或导入脚本的错。但事实证明,当一个主题回复(在 Drupal 术语中是“评论”)被编辑时,它有时会更改 created 时间戳。据我所知,它应该更改 changed 时间戳。但尽管 Drupal 中存在这个错误,它仍然能保持评论的线程顺序。但是,Discourse 的 Drupal 导入脚本的工作方式是,它似乎按 created 时间戳对回复进行排序(尽管我在 drupal.rb 脚本中没有看到任何 ORDER 子句)。根据我在 phpMyAdmin 上对 Drupal 数据库的测试,它似乎只需要一个 ORDER BY c.cid ASC 来通过原始 Drupal 评论 ID cid 保持正确的线程顺序,而 cid 是顺序的且永不改变。但我不知道 Discourse 导入器是否允许顺序回复具有失序的日期,以及/或者它是否会自行按帖子日期进行排序?我想听听 drupal.rb 导入器的原始创建者(以及其他任何人)的意见,这是否可行,是否会有任何意外后果?

我认为(但我不确定,因为 Drupal 的数据库让我很困惑),你可以调整查询,从原始帖子中提取创建时间,而不是编辑后的时间。

我认为有一个表包含原始帖子/时间,另一个表包含编辑内容。

我认为按 cid 排序不会有什么坏处。

1 个赞

这真的说不通。问题是这样的,两个高亮显示的行应该是主题中的第二和第三个回复,但在 Discourse 中,它们排在第 500 位之后,因为那是它们的创建时间戳。

当然,Drupal 决定将 createdchanged 设置为相同的值……而且这种情况只偶尔发生,我无法通过编辑旧帖子来重现它。但是,在多个长期运行的主题中,我遇到了同样的问题,主题的发布者发布了帖子,然后立即发布了一两个带有“reserved”字样的跟帖,以便以后添加额外信息,而他是在几年后才添加的。

这似乎说得通,但这里是同一个有问题的编辑评论在它使用的两个表中的分布情况:


1 个赞

好的,看起来这可行,它修复了我发现的两个混乱的线程,并且似乎没有损害其他任何东西。

  def import_replies

    batches(BATCH_SIZE) do |offset|
      results = mysql_query(<<-SQL
        SELECT c.cid, c.pid, c.nid, c.uid, c.created,
               f.comment_body_value body,
               f.comment_body_format format
          FROM comment c,
               field_data_comment_body f,
               node n
         WHERE c.cid = f.entity_id
           AND n.nid = c.nid
           AND c.status = 1
           AND n.type IN ('poll', 'forum')
           AND n.status = 1
           AND c.created > UNIX_TIMESTAMP(STR_TO_DATE('#{IMPORT_AFTER}', '%Y-%m-%d'))
         ORDER BY c.cid ASC  #<--- Fixed
         LIMIT #{BATCH_SIZE}
        OFFSET #{offset}
      SQL
      ).to_a
1 个赞

嗯,看起来这给我带来了麻烦。由于 postprocess_posts 函数会用新的 Discourse URL 替换旧的内部链接,我在代码中为我的导入器创建的 Wayback Machine 上的旧 Drupal 投票链接 https://web.archive.org/web/20230101093741/https://MyOldForum.com/node/98765 做了一个例外。但显然出了问题,因为我在生产迁移的站点上注意到链接变成了 https://web.archive.org/web/20230101093741/https://MyOldForum.com/t/-/12345

所以现在我不再处于迁移容器的上下文中了,原始的 Drupal 节点 nid 是否仍然可以在 Discourse 主题数据库表中找到?如果是的话,似乎可以在 Rails 控制台中对所有包含“View this poll on the Wayback Machine”的第一篇帖子进行字符串替换,然后将
https://web.archive.org/web/20230101093741/https://MyOldForum.com/t/-/[01234567890]*
替换为
https://web.archive.org/web/20230101093741/http://MyOldForum.com/node/$original_nid

这是我原来的投票导入函数:

    def import_poll_topics
    puts '', "importing poll topics"

    polls = mysql_query(<<-SQL
      SELECT n.nid nid, n.title title, n.uid uid, n.created created, n.sticky sticky, taxonomy_index.tid tid, node_counter.totalcount views
        FROM node n
        LEFT JOIN taxonomy_index ON n.nid = taxonomy_index.nid
        LEFT JOIN node_counter ON n.nid = node_counter.nid
       WHERE n.type = 'poll'
         AND n.status = 1
    SQL
    ).to_a

    create_posts(polls) do |topic|
      {
        id: "nid:#{topic['nid']}",
        user_id: user_id_from_imported_user_id(topic['uid']) || -1,
        category: category_id_from_imported_category_id(topic['tid']),
        # Use TEMPmyoldforum.com or else postprocess_posts() will try to convert the Wayback Machine /node/YYY link
        raw: "### View this poll on the Wayback Machine:\n**https://web.archive.org/web/20230101093741/http://TEMPmyoldforum.com/node/#{topic['nid']}**",
        created_at: Time.zone.at(topic['created']),
        pinned_at: topic['sticky'].to_i == 1 ? Time.zone.at(topic['created']) : nil,
        title: topic['title'].try(:strip),
        views: topic['views'],
        custom_fields: { import_id: "nid:#{topic['nid']}" }
      }
    end
  end

是的。

t=Topic.find(1234)
t.custom_fields
t.custom_fields['import_id']
1 个赞