nodeclub迁移至nodebb

╄→гoц情女王★ 提交于 2019-12-04 20:02:49

背景


在嵌入式部门工作时搭建了一个论坛,用于每周末大家做周末总结,并制定下周计划。
在调研云计算厂商时发现,好多公司内部都有论坛,用于技术交流分享想法和讨论问题,于是萌生了把之前搭建的论坛推广全公司使用的想法。

遇到了问题


由于之前用nodeclub搭建的论坛比较简单,可用性比较差,尤其在权限控制上粒度太高,只有管理员和普通用户的区别,如果全公司使用,可能有些板块是部门内部的板块不便开放给其他部门,或者有些板块可以对公司外开放,再或者帖子中上传附件的功能,nodeclub只支持上传图片,需要借助七牛云,这些功能其实通过修改nodeclub的源码都可以实现,但是我真的没时间写。

遇见nodebb



在之前用nodeclub搭建论坛的时候调研过nodebb,发现nodebb的代码很复杂,并且在我机器上搭建测试了一下发现有点卡顿,和简洁轻便的nodeclub相比我还是选择了nodeclub。但是这次不同了,nodebb社区不断的更新迭代以及生态环境下多种插件的支持使得nodebb增加新功能的时候变得非常简单。并且经过了多个版本的迭代,nodebb已经很稳定,并且想vue的论坛、青云论坛都在使用nodebb进行搭建。

搭建nodebb


准备工作


  • MongoDB
  • nodejs

nodejs推荐到淘宝npm站下载 下载链接
mongodb使用官网推荐的安装方式即可。对于linux系统,如果想加速下载,可使用清华tuna源 帮助链接

安装


以上准备工作做完之后按照官方的推荐的流程即可 官方安装流程

遇到问题


发现问题

  1. 前端界面一直提示已断开连接
  2. 权限问题
  3. 邮件问题
  4. 自定义header、sidebar、footer问题
  5. 迁移问题

解决问题

  1. 浏览器F12调试后发现是websocket连接不上,websocket的连接地址是127.0.0.1:4567 也就是安装时默认的地址和端口,所以连不上是对的。修改nodebb目录下的config.js 修改ip为nodebb所在服务器的ip或者如果做端口映射了修改外对外访问的ip再或者修改为域名。

  2. 公司内部的板块不想让游客查看,但是有些板块应该能够对外开放。因此要能针对不同的板块设置不同的权限,好在nodebb自己解决了这个问题,在每个板块的权限设置里都针对不同的用户预置了“查看权限”、“发帖权限”、“审核权限”等,就很好的解决了这个问题。并且在用户注册上具有多种模式,比较适用公司的是邀请模式,管理员可对要假如社区的成员进行邀请、另一种是通过LDAP插件使用公司的LDAP服务器进行验证,但是测试时发现工作不正常,可能是这个插件的更新没有跟上nodebb的更新速度导致的。

  3. 邮件使用了nodebb-plugin-emailer-smtp-emz插件,使用邮箱的smtp服务进行相应的设置即可。SMTP的设置在自己的邮箱即可找到,例如使用公司的邮箱:

  4. nodebb的灵活性就在于通过后台配置而不是修改源码的方式即可修改论坛的大致外观,并且nodebb原生支持了bootstrap。

  5. 之前用nodeclub搭建的论坛内容要迁移至nodebb上,这部分内容用一个单独的章节描述。

迁移


由于nodebb和nodeclub两个系统的数据库虽然都是使用mongoDB但是schema肯定是不一样的。本来想通过读取nodeclub数据的内容然后按照nodebb的schema再写回去,但是发现nodebb存储的太复杂了,一个collection中的格式千奇百怪,还没理解他的存储规律,如果按照这个思路做迁移肯定要读nodebb的代码,否则无法完成这个任务,遂放弃。

由于nodeclub数据库的格式浅显易懂,以前帖子的导出肯定是没问题的。本来想截图,但是发现nodeclub的数据库已经被删了。

既然帖子获取没有问题了,接下来的问题就是如何导入到新的nodebb中,既然直接写入数据库的无望了,就得考虑另外一种方法,现在所有的产品都会考虑二次开发,给别人开放API接口,nodebb也是,通过安装nodebb-plugin-write-api插件解决了API问题,同时它通过token解决了安全验证的问题。

接下来就是具体的代码实现,由于这次是技术分享,主要面向nodejs技术小白,所以我会把如何使用包及如何分析也会比较详尽的描述。

撸代码


其实写这段程序的代码很简单,先交代一下使用了哪些js包:

"mongodb": "^2.2.31"
"moment": "^2.18.1"
"request": "^2.82.0"

首先建立nodejs工程:

npm init

根据需要填写相应的信息后,安装依赖包:

npm install mongodb --save
npm install moment--save
npm install request--save

mongodb这个包解决了用nodejs连接mongDB数据的问题,它是mongoDB官方写的nodejs数据库驱动。像我们更常用的mongoose.js也是基于mongodb.js做的。

moment是一个功能强大的解析、操作、格式化、验证时间的库,它能将时间输出成你想要的格式,如果要在nodejs中折腾时间信息,在原生的date对象满足不了需求的情况下优先考虑使用moment.js

requestrequest包是当你要用http做一些事的时候优先应该想到的包,它能发起各种http的请求。

先把所有代码抛出来,再慢慢解释:

var request = require('request');
var mongodb = require('mongodb');
var moment = require('moment')
var MongoClient = require('mongodb').MongoClient;
var DB_CONN_STR = 'mongodb://192.168.xxx.xxx:27017/node_club_dev';
const tabName = 'discuss';
const CID = 2;
let options = {
    url: 'http://192.168.xxx.xxx:4567/api/v1/topics',
    headers: {
        'Authorization': 'Bearer aaxxxxxxxxxxxxxxxxxxx'
    },
    form: {
        cid: CID,
        title: "",
        content: ""
    }
};

function callback(error, response, body) {
    if(!error){
        console.log("本帖迁移完成")
    }else{
        console.log(error)
    }

}

let cursorCloseed = false;

MongoClient.connect(DB_CONN_STR, function (err, db) {
    console.log("连接成功!");
    selectData(db, function (result) {
        console.log(result);
        db.close();
    });
});

var topicObjects = [];
var selectData = function (db, callback) {
    //连接到表
    var collection = db.collection('topics');
    //查询数据
    var whereStr = {"tab": tabName};
    collection.find(whereStr, function (error, cursor) {
        cursor.toArray(function(err, docs){
            if(!err){
                let count = 0;
                setInterval(function () {
                    if(count < docs.length){
                        doc = docs[count++]
                        if(!doc.deleted){
                            var title = doc.title;
                            var content = doc.content;
                            var date = new Date(doc.update_at);
                            var dayWrapper = moment(date);
                            options.form.title = title + "【迁移自" + dayWrapper.format("YY-MM-DD hh:mm:ss") + "】";
                            options.form.content = content;
                            request.post(options, callback);
                            console.log(options.form.title+"  迁移中...")
                        }
                    }else{
                        console.log("迁移完成!")
                    }
                },50)

            }

        })

    });
}


稍微解释一下:
DB_CONN_STR是数据的地址,nodeclub的mongoDB在192.168.xxx.xxx这台服务器上使用默认的27017端口,然后数据库的名字叫做node_club_dev

tabName是nodeclub中每个板块的名字,截至到迁移前,已经创建的板块有:sharenoticediscusssum对应的板块就是“分享板块”、“通知板块”、“讨论板块”、“总结板块”。

CID是nodebb中每个板块的cid,这个cid决定了使用api接口发帖所在版块的位置。

mongodb.js的使用方法,参考他的readme,首先如何使用mongdb client与数据库连接


然后,找到这个数据库下面名为topics的collection,按照条件进行查找:

按照官网的例子,我们就把数据全找出来并转换成array放到了docs中。
这样数据就获取出来,接下来的工作就是使用request.js将帖子通过nodebb的api,post一个帖子。去你npm官网看看request.js如何使用,由于接口只支持x-www-form-urlencoded的数据上传,所以找到这个字眼后我们在它的文档中可以找到:


另外,api中验证的token要放入http头部,因此在头部加入'Authorization': 'Bearer aaxxxxxxxxxxxxxxxxxxx',这样request要发送的数据包就组合好了,最后为了避开nodebb设置的流量控制机制,在批量发帖的两个帖子之间留有一定的间隔时间,使用setInterval即可解决。这样,迁移就结束了,这个迁移不需要服务器宕机,而且是必须不宕机哦。


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!