V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
gj9590
V2EX  ›  程序员

开始从 discuzX3.4 迁移到 nodebb

  •  
  •   gj9590 · 311 天前 · 1546 次点击
    这是一个创建于 311 天前的主题,其中的信息可能已经有所发展或是发生改变。

    论坛这事儿

    论坛这东西现在已经变得非常的小众,我玩论坛始于 25 年前(暴露了年龄哈哈),现在逛论坛的时间并不多了,最多看看知乎或者公众号文章,也会偶尔跟着潮流制作一些视频。慢慢发现,好的内容还是很受大家欢迎,一个好的视频内容(不是只流量大的)其实也要有好的文案。本人写东西也只是才是这几年的事,偶尔在实体杂志上写一小方块东西。码字是很花时间的,但也是对自己知识和智慧的集中考验。

    论坛相对于公众号文章和即时聊天来看,是一个奇怪的中间产品,口水多但有时能积累起一些很有干货的主题,十分精彩。

    最近想接手一个论坛,用于自己写东西做知识梳理和内容积累,也顺便尝试汇集志同道合的朋友。

    现代论坛

    旧论坛是 discuzX3.4 ,看了一下对比现代的 web 产品,多少有点倒胃口。功能相当多,界面繁复,速度又慢。。。

    看了下三大现代论坛 flarum, nodebb, discourse ,最终选了在功能和资源消耗折中的 nodebb 。原论坛用户数量和帖子积累得不少,所以想办法把数据尽可能迁移过去,发现网上这方面资料并不多,有的也很旧了。开这个帖子记录一下,也希望对其他朋友有用。我的代码都是自学过来的,学得也支离破碎,因为工作用不上,所以纯靠兴趣发动,自己根本算不上程序员,特别希望大家帮我挑错,支招。

    12 条回复    2024-02-19 15:19:40 +08:00
    gj9590
        1
    gj9590  
    OP
       311 天前
    首先要了解下 discuzX3.4 和 nodebb 的数据库结构,discuzX 用的是 mysql ,nodebb 用的是 mongodb 。

    最重要的当然是**用户**相关的数据表和**帖子**数据表。discuzX 能查到数据表字典,nodebb 只能自己用 mongodb 的 admin 工具看了。

    ### 一、用户数据

    **2 、nodebb 和 discuz 数据表的对照**

    Nodebb 用户表须用的数据(字段):

    ```json
    db.objects.findOne({username:"admin"}) -->
    {
    "_id" : ObjectId("65cb8801e09f69ff71141520"),
    "_key" : "user:1",
    "joindate" : 1707837441083,
    "lastonline" : 1708000177292,
    //"status" : "online",
    "uid" : 1,
    "username" : "admin",
    //"userslug" : "admin",
    "password" : "$2a$12$VIKLGFC3AS1B4sDuVNivIOQO1HVpxjdOJXyUDBnDZqbu5nK",
    //"password:shaWrapped" : 1,
    "email" : "[email protected]",
    //"email:confirmed" : 1,
    //"groupTitle" : "[\"\"]",
    //"gdpr_consent" : 1,
    "profileviews" : 0, // 空间点击数 views
    "reputation" : 0, // 声誉,积分 credits
    "topiccount" : 1, // 主题 threads
    "lastposttime" : 1707837441933,
    "postcount" : 1, // 帖子 posts (包含了主题)
    //"rss_token" : "17305070-9558-4f2a-bef1-aba7902e0990",
    "picture" : "/assets/uploads/profile/1-profileavatar-1707989852545.jpeg",
    "uploadedpicture" : "/assets/uploads/profile/1-profileavatar-1707989852545.jpeg",
    "fullname" : "全名 guojin",
    "aboutme" : "关于我是一个管理员",
    "birthday" : "2024-02-15",
    "location" : "广州",
    "signature" : "签名:我是一个管理员",
    "website" : "https://weibo.com/我的网"
    }
    ```

    discuzX 的表分得比较散,有好几个表:

    pre_common_member 用户主表

    | 字段名 | 数据类型 | 默认值 | 允许非空 | 自动递增 | 备注 |
    | --- | --- | --- | --- | --- | --- |
    | uid | mediumint(8) unsigned | | NO | 是 | 会员 id |
    | email | char(40) | | NO | | 邮箱 |
    | username | char(15) | | NO | | 用户名 |
    | password | char(32) | | NO | | 密码 |
    | status | tinyint(1) | 0 | NO | | 判断用户是否已经删除 需要 discuz 程序加判断,并增加整体清理的功能。原 home 字段为 flag |
    | emailstatus | tinyint(1) | 0 | NO | | email 是否经过验证 home 字段为 emailcheck |
    | avatarstatus | tinyint(1) | 0 | NO | | 是否有头像 home 字段为 avatar |
    | videophotostatus | tinyint(1) | 0 | NO | | 视频认证状态 home |
    | adminid | tinyint(1) | 0 | NO | | 管理员 id |
    | groupid | smallint(6) unsigned | 0 | NO | | 会员组 id |
    | groupexpiry | int(10) unsigned | 0 | NO | | 用户组有效期 |
    | extgroupids | char(20) | | NO | | 扩展用户组 |
    | regdate | int(10) unsigned | 0 | NO | | 注册时间 |
    | credits | int(10) | 0 | NO | | 总积分 |
    | notifysound | tinyint(1) | 0 | NO | | 短信声音 |
    | timeoffset | char(4) | | NO | | 时区校正 |
    | newpm | smallint(6) unsigned | 0 | NO | | 新短消息数量 |
    | newprompt | smallint(6) unsigned | 0 | NO | | 新提醒数目 |
    | accessmasks | tinyint(1) | 0 | NO | | 标志 |
    | allowadmincp | tinyint(1) | 0 | NO | | 标志 |
    | onlyacceptfriendpm | tinyint(1) | 0 | NO | | 是否只接收好友短消息 |
    | conisbind | tinyint(1) unsigned | 0 | NO | | 用户是否绑定 QC |

    uc_members 用户表

    | 字段名 | 数据类型 | 默认值 | 允许非空 | 自动递增 | 备注 |
    | --- | --- | --- | --- | --- | --- |
    | uid | mediumint(8) unsigned | | NO | 是 | 用户 ID |
    | username | char(15) | | NO | | 用户名 |
    | password | char(32) | | NO | | 密码 |
    | email | char(32) | | NO | | 用户 Email |
    | myid | char(30) | | NO | | 漫游 id |
    | myidkey | char(16) | | NO | | 漫游 id |
    | regip | char(15) | | NO | | 注册 IP |
    | regdate | int(10) unsigned | 0 | NO | | 注册时间 |
    | lastloginip | int(10) | 0 | NO | | 上次登陆的 IP(程序转换成数值类型) |
    | lastlogintime | int(10) unsigned | 0 | NO | | 上次登录的时间 |
    | salt | char(6) | | NO | | 密码干扰串,用来和密码进行配合验证,防止被暴力破解 |
    | secques | char(8) | | NO | | 用户的安全提问 |

    pre_common_member_field_forum 用户论坛字段表

    | 字段名 | 数据类型 | 默认值 | 允许非空 | 备注 |
    | --- | --- | --- | --- | --- |
    | uid | mediumint(8) unsigned | | NO | 会员 id |
    | publishfeed | tinyint(3) | 0 | NO | 用户自定义发送哪些类型的 feed(原字段为 customaddfeed) |
    | customshow | tinyint(1) unsigned | 26 | NO | 自定义帖子显示模式 |
    | customstatus | varchar(30) | | NO | 自定义头衔 |
    | medals | text | | NO | 勋章信息 |
    | sightml | text | | NO | 签名 |
    | groupterms | text | | NO | 公共用户组 |
    | authstr | varchar(20) | | NO | 找回密码验证串 |
    | groups | mediumtext | | NO | 用户所有群组 |
    | attentiongroup | varchar(255) | | NO | 用户偏好 |

    pre_common_member_profile 用户栏目表

    | 字段名 | 数据类型 | 默认值 | 允许非空 | 备注 |
    | --- | --- | --- | --- | --- |
    | uid | mediumint(8) unsigned | | NO | 会员 id |
    | realname | varchar(255) | | NO | 实名 |
    | gender | tinyint(1) | 0 | NO | 性别 (0:保密 1:男 2:女) |
    | birthyear | smallint(6) unsigned | 0 | NO | |
    | birthmonth | tinyint(3) unsigned | 0 | NO | |
    | birthday | tinyint(3) unsigned | 0 | NO | |
    | constellation | varchar(255) | | NO | 星座(根据生日自动计算) |
    | zodiac | varchar(255) | | NO | 生肖(根据生日自动计算) |
    | telephone | varchar(255) | | NO | 固定电话 |
    | mobile | varchar(255) | | NO | 手机 |
    | idcardtype | varchar(255) | | NO | 证件类型:身份证 护照 军官证等 |
    | idcard | varchar(255) | | NO | 证件号码 |
    | address | varchar(255) | | NO | 邮寄地址 |
    | zipcode | varchar(255) | | NO | 邮编 |
    | nationality | varchar(255) | | NO | 国籍 |
    | birthprovince | varchar(255) | | NO | 出生省份 |
    | birthcity | varchar(255) | | NO | 出生城市 |
    | birthdist | varchar(20) | | NO | 出生行政区/县 |
    | birthcommunity | varchar(255) | | NO | 出生小区 |
    | resideprovince | varchar(255) | | NO | 居住省份 |
    | residecity | varchar(255) | | NO | 居住城市 |
    | residedist | varchar(20) | | NO | 居住行政区/县 |
    | residecommunity | varchar(255) | | NO | 居住小区 |
    | residesuite | varchar(255) | | NO | 小区、写字楼门牌号 |
    | graduateschool | varchar(255) | | NO | 毕业学校 |
    | company | varchar(255) | | NO | 公司 |
    | education | varchar(255) | | NO | 学历 |
    | occupation | varchar(255) | | NO | 职业 |
    | position | varchar(255) | | NO | 职位 |
    | revenue | varchar(255) | | NO | 年收入 |
    | affectivestatus | varchar(255) | | NO | 情感状态 |
    | lookingfor | varchar(255) | | NO | 交友目的(交友类型) |
    | bloodtype | varchar(255) | | NO | 血型 |
    | height | varchar(255) | | NO | 身高 |
    | weight | varchar(255) | | NO | 体重 |
    | alipay | varchar(255) | | NO | 支付宝帐号 |
    | icq | varchar(255) | | NO | ICQ |
    | qq | varchar(255) | | NO | QQ |
    | yahoo | varchar(255) | | NO | YAHOO |
    | msn | varchar(255) | | NO | MSN |
    | taobao | varchar(255) | | NO | 阿里旺旺 |
    | site | varchar(255) | | NO | 主页 |
    | bio | text | | NO | 自我介绍 来自论坛 bio 字段 |
    | interest | text | | NO | 兴趣爱好 |
    | field1 | text | | NO | 自定义字段 1 |
    | field2 | text | | NO | 自定义字段 2 |
    | field3 | text | | NO | 自定义字段 3 |
    | field4 | text | | NO | 自定义字段 4 |
    | field5 | text | | NO | 自定义字段 5 |
    | field6 | text | | NO | 自定义字段 6 |
    | field7 | text | | NO | 自定义字段 7 |
    | field8 | text | | NO | 自定义字段 8 |

    pre_common_member_count 用户统计表

    | 字段名 | 数据类型 | 默认值 | 允许非空 | 备注 |
    | --- | --- | --- | --- | --- |
    | uid | mediumint(8) unsigned | | NO | 会员 id |
    | extcredits1 | int(10) | 0 | NO | 声望 |
    | extcredits2 | int(10) | 0 | NO | 金钱 |
    | extcredits3 | int(10) | 0 | NO | 扩展 |
    | extcredits4 | int(10) | 0 | NO | 扩展 |
    | extcredits5 | int(10) | 0 | NO | 扩展 |
    | extcredits6 | int(10) | 0 | NO | 扩展 |
    | extcredits7 | int(10) | 0 | NO | 扩展 |
    | extcredits8 | int(10) | 0 | NO | 扩展 |
    | friends | smallint(6) unsigned | 0 | NO | 好友个数 home |
    | posts | mediumint(8) unsigned | 0 | NO | 帖子数 |
    | threads | mediumint(8) unsigned | 0 | NO | 主题数 |
    | digestposts | smallint(6) unsigned | 0 | NO | 精华数 |
    | doings | smallint(6) unsigned | 0 | NO | 记录数 |
    | blogs | smallint(6) unsigned | 0 | NO | 日志数 |
    | albums | smallint(6) unsigned | 0 | NO | 相册数 |
    | sharings | smallint(6) unsigned | 0 | NO | 分享数 |
    | attachsize | int(10) unsigned | 0 | NO | 上传附件占用的空间 home |
    | views | mediumint(8) unsigned | 0 | NO | 空间查看数 |
    | oltime | smallint(6) unsigned | 0 | NO | 在线时间 |
    | todayattachs | smallint(6) unsigned | 0 | NO | 当天上传附件数 |
    | todayattachsize | int(10) unsigned | 0 | NO | 当天上传附件容量 |
    | feeds | mediumint(8) unsigned | 0 | NO | 广播数 |
    | follower | mediumint(8) unsigned | 0 | NO | 听众数量 |
    | following | mediumint(8) unsigned | 0 | NO | 收听数量 |
    | newfollower | mediumint(8) unsigned | 0 | NO | 新增听众数量 |
    | blacklist | mediumint(8) unsigned | 0 | NO | 拉黑用户数 |

    pre_common_member_status 用户状态表

    | 字段名 | 数据类型 | 默认值 | 允许非空 | 备注 |
    | --- | --- | --- | --- | --- |
    | uid | mediumint(8) unsigned | | NO | 会员 id |
    | regip | char(15) | | NO | 注册 IP |
    | lastip | char(15) | | NO | 最后登录 IP |
    | lastvisit | int(10) unsigned | 0 | NO | 最后访问 |
    | lastactivity | int(10) unsigned | 0 | NO | 最后活动 |
    | lastpost | int(10) unsigned | 0 | NO | 最后发表 |
    | lastsendmail | int(10) unsigned | 0 | NO | 上次发送 email 时间 home 原字段为 lastsend |
    | invisible | tinyint(1) | 0 | NO | 是否隐身登录 |
    | buyercredit | smallint(6) | 0 | NO | 买家信用等级及积分 |
    | sellercredit | smallint(6) | 0 | NO | 卖家信用等级及积分 |
    | favtimes | mediumint(8) unsigned | 0 | NO | 个人空间收藏次数 |
    | sharetimes | mediumint(8) unsigned | 0 | NO | 个人空间分享次数 |
    | profileprogress | tinyint(2) unsigned | 0 | NO | 个人资料完成度 |
    NessajCN
        2
    NessajCN  
       311 天前   ❤️ 1
    你这三个也老的不行了
    要不你看看这个
    https://github.com/LemmyNet/lemmy
    gj9590
        3
    gj9590  
    OP
       311 天前
    @NessajCN 谢谢推荐,我去了解一下。markdown 不熟,上面那个回复有表格不知道为什么系统没有转成 markdown
    winzkh
        4
    winzkh  
       311 天前   ❤️ 1
    @gj9590 V2EX 的回复不支持 markdown
    gj9590
        5
    gj9590  
    OP
       311 天前
    @winzkh 原来是这样,谢谢!
    matolv
        6
    matolv  
       311 天前 via Android
    劝楼主用 discourse ,基本全程傻瓜操作,docker 更符合现代运维方式。nodebb 很多插件都过时没法用了,社区不能提供稳定支持。如果楼主是前端,能手撸 js 代码当我没说
    gj9590
        7
    gj9590  
    OP
       311 天前
    @matolv 谢谢你的建议,搭过一次,感觉后台不太友好,还有就是非常消耗资源,请教一下至少需要多少内存和 CPU 来运行呢
    gj9590
        8
    gj9590  
    OP
       311 天前
    neutrino
        9
    neutrino  
       311 天前 via Android
    建议还是用 Discuz ,刚从 3.3 升级到 3.5 ,感觉良好。一定要换的话也不要选 MongoDB 的…找个关系型数据库把吧
    gj9590
        10
    gj9590  
    OP
       311 天前
    @neutrino 谢谢建议,我还在本地 nodebb 测试中,3.5 也可以同时测试,有好的升级教程希望你发一个谢谢!
    matolv
        11
    matolv  
       311 天前 via Android
    @gj9590 rebuild 的时候会消耗比较多 cpu 资源,平时基本不会,内存占用不低,2g 起步,实际最好 4-10G 。我直接搭在 40c 256g 母鸡上,对资源消耗不太敏感,只对功能完善度,bug 修复速度是否敏感。nodebb 差 discourse 太多,要么就停留在 discuz ,没什么不能用的,要转就直接 discourse 一步到位。
    neutrino
        12
    neutrino  
       311 天前 via Android
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5422 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 07:26 · PVG 15:26 · LAX 23:26 · JFK 02:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.