开始从 discuzX3.4 迁移到 nodebb

273 天前
 gj9590

论坛这事儿

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

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

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

现代论坛

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

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

1458 次点击
所在节点    程序员
12 条回复
gj9590
273 天前
首先要了解下 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" : "32342@yeah.net",
//"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
273 天前
你这三个也老的不行了
要不你看看这个
https://github.com/LemmyNet/lemmy
gj9590
273 天前
@NessajCN 谢谢推荐,我去了解一下。markdown 不熟,上面那个回复有表格不知道为什么系统没有转成 markdown
winzkh
273 天前
@gj9590 V2EX 的回复不支持 markdown
gj9590
273 天前
@winzkh 原来是这样,谢谢!
matolv
273 天前
劝楼主用 discourse ,基本全程傻瓜操作,docker 更符合现代运维方式。nodebb 很多插件都过时没法用了,社区不能提供稳定支持。如果楼主是前端,能手撸 js 代码当我没说
gj9590
273 天前
@matolv 谢谢你的建议,搭过一次,感觉后台不太友好,还有就是非常消耗资源,请教一下至少需要多少内存和 CPU 来运行呢
gj9590
273 天前
neutrino
273 天前
建议还是用 Discuz ,刚从 3.3 升级到 3.5 ,感觉良好。一定要换的话也不要选 MongoDB 的…找个关系型数据库把吧
gj9590
272 天前
@neutrino 谢谢建议,我还在本地 nodebb 测试中,3.5 也可以同时测试,有好的升级教程希望你发一个谢谢!
matolv
272 天前
@gj9590 rebuild 的时候会消耗比较多 cpu 资源,平时基本不会,内存占用不低,2g 起步,实际最好 4-10G 。我直接搭在 40c 256g 母鸡上,对资源消耗不太敏感,只对功能完善度,bug 修复速度是否敏感。nodebb 差 discourse 太多,要么就停留在 discuz ,没什么不能用的,要转就直接 discourse 一步到位。
neutrino
272 天前

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1016280

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX