美文网首页
3.MongoDB配置与基础使用

3.MongoDB配置与基础使用

作者: virl | 来源:发表于2019-03-03 22:56 被阅读0次

MongoDB配置与基础使用

MongoDB是业内使用非常成熟和广泛的非关系型数据库,在业务还不成熟,数据结构还不确定的情况下,扩展性非常强。在教程中使用非常方便,因为我们的数据格式会随着功能的扩充不断的优化。

添加依赖

使用官方的mongodb Node.js驱动
修改package.js文件添加依赖

"mongodb": "3.1.13"

封装调用

目录common下创建db目录,创建文件mongo_ex.js

var MongoClient = require('mongodb').MongoClient;

class CollectionEx {
    constructor(db, collection_name) {
        this.collection = db.collection(collection_name)
    }

    async insertOne(doc, options) {
        return await this.collection.insertOne(doc, options).insertedId;
    }

    async insertMany(docs, options) {
        return await this.collection.insertMany(docs, options).insertedIds;
    }

    async findOne(filter) {
        return await this.collection.findOne(filter);
    }

    async findMany(filter) {
        let cursor = this.collection.find(filter)
        return await cursor.toArray()
    }

    async deleteOne(filter, options) {
        let result = await this.collection.deleteOne(filter, options);
        return result.deletedCount;
    }

    async deleteMany(filter) {
        let result = await this.collection.deleteMany(filter);
        return result.deletedCount;
    }

    async updateOne(filter, update) {
        let result = await this.collection.updateOne(filter, update);
        return result.modifiedCount;
    }

    async updateMany(filter, update) {
        let result = await this.collection.updateMany(filter, update);
        return {
            matched_count: result.matchedCount,
            modified_count: result.modifiedCount
        };
    }
}


class ClientEx {
    constructor() {
        this.client = null;
        this.db_map = {};
    }

    async connect(uri, options) {
        this.client = await MongoClient.connect(uri, options);
    }

    getDB(db_name) {
        if (!this.isConnected()) {
            throw new Error('mongo is not connected');
        }
        let db = this.db_map[db_name];
        if (!db) {
            db = this.client.db(db_name);
            this.db_map[db_name] = db;
        }
        return db;
    }

    isConnected() {
        return (this.client && this.client.isConnected())
    }

    async close() {
        if (!this.isConnected()) {
            return;
        }
        this.db_map = {}
        this.client.close();
        this.client = null;
    }
}

module.exports = {
    CollectionEx,
    ClientEx
}

大部分内容都很简单,只是简单的一个封装,很多人会有疑问,这么做的目的有什么用?不是脱裤子放屁多一道手续么?
这样做的目的是为了把与数据库直接交互的代码抽离出来,如果后续有其他的想法,比如增加统一的数据库日志,想要做主从库的读写分离,只需要在这个层面进行修改而调用方基本不需要改动。

初始化数据库

根目录下创建文件dbs.js

const MongoEx = require('./common/db/mongo_ex')
const Config = require('./configs')
const MainMongoConfig = Config.mongo

module.exports = {
    setupDB: async () => {
        let main_mongo = new MongoEx.ClientEx()
        await main_mongo.connect(MainMongoConfig.uri, MainMongoConfig.options)
        module.exports.main_mongo = main_mongo;
    }
}

功能就是完成数据库的初始建连操作。
对应在需要修改配置文件
改成这样子:

module.exports = {
    port: 3000,
    mongo: {
        uri: 'mongodb://127.0.0.1:27017',
        options: undefined //具体配置可以参照mongo文档
    }
}

测试环境我是连接的本机的数据库

初始化数据库

然后修改app.js 增加初始化数据库的代码,修改完成如下:

const DBS = require('./dbs')

async function startApp() {
    const app = new Koa();
    app.use(BodyParser());
    app.use(CtxEx);
    Router.setupRouter(app);

    await DBS.setupDB();

    app.listen(Config.port);
    console.log(`server start of:${Config.port}`);
}

示例数据库的使用

下面展示怎么对数据库做操作,以及操作之后的结果
创建目录models
创建文件test.js

const DBS = require('../dbs')
const CollectionEx = require('../common/db/mongo_ex').CollectionEx
async function testMongoActions() {
    let collection = new CollectionEx(DBS.main_mongo.getDB('test'), 'test')
    await collection.deleteMany({})
    await showAll(collection, 'after delete all')
    await collection.insertOne({
        name: 'xiaoming',
        pwd: 'good'
    })
    await showAll(collection, 'after insert one')
    await collection.insertMany([{
        name: 'zhangsan',
        pwd: 'good'
    }, {
        name: 'lisi',
        pwd: 'good'
    }])
    await showAll(collection, 'after insert many')
    let xiaoming = await collection.findOne({
        name: 'xiaoming'
    })
    console.log(`find one of xiaoming:${JSON.stringify(xiaoming)}`)
    await collection.updateOne({
        name: 'xiaoming'
    }, {
        $set: {
            pwd: 'not so good'
        }
    })
    xiaoming = await collection.findOne({
        name: 'xiaoming'
    })
    console.log(`find one of xiaoming after update:${JSON.stringify(xiaoming)}`)
    await collection.updateMany({}, {
        $set: {
            pwd: 'very good'
        }
    })
    await showAll(collection, 'after update many')
    await collection.deleteOne({
        name: 'xiaoming'
    })
    await showAll(collection, 'after delet one')
    await collection.deleteMany({})
    await showAll(collection, 'after delet many')
}

async function showAll(collection, msg) {
    console.log('**********************    ' + msg + ' start')
    let items = await collection.findMany({})
    for (let item of items) {
        console.log(JSON.stringify(item))
    }
    console.log('**********************    ' + msg + ' end')
}

module.exports = testMongoActions

这个文件做的事情就是展示对数据库封装接口的调用,以及调用后的结果展示。
再在models目录下创建文件index.js

module.exports.test = require('./test')

这个文件的目的,就是对目录的导入(require)实际导入的就是对应目录下的index.js文件
现在增加对封装的test做调用代码
修改controllers/hello.js文件
文件头添加这两行:

const Models = require('../models')
const Test = Models.test

增加如下导出函数

'GET test': async (ctx, next) => {
    await Test()
    ctx.rest()
},

现在可以试试在Postman中对/test路由执行GET方法。
可以在命令行输出中看到这样的结果:

> kite_server@1.0.0 start /Users/virl/wksp/kite/kite_server
> node app.js

GET /hello/hello
GET /test
GET /hello
POST /hello
GET /error
(node:15563) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
server start of:3000
**********************    after delete all start
**********************    after delete all end
**********************    after insert one start
{"_id":"5c7bea9aa6cee73ccb23d5b7","name":"xiaoming","pwd":"good"}
**********************    after insert one end
**********************    after insert many start
{"_id":"5c7bea9aa6cee73ccb23d5b7","name":"xiaoming","pwd":"good"}
{"_id":"5c7bea9aa6cee73ccb23d5b8","name":"zhangsan","pwd":"good"}
{"_id":"5c7bea9aa6cee73ccb23d5b9","name":"lisi","pwd":"good"}
**********************    after insert many end
find one of xiaoming:{"_id":"5c7bea9aa6cee73ccb23d5b7","name":"xiaoming","pwd":"good"}
find one of xiaoming after update:{"_id":"5c7bea9aa6cee73ccb23d5b7","name":"xiaoming","pwd":"not so good"}
**********************    after update many start
{"_id":"5c7bea9aa6cee73ccb23d5b7","name":"xiaoming","pwd":"very good"}
{"_id":"5c7bea9aa6cee73ccb23d5b8","name":"zhangsan","pwd":"very good"}
{"_id":"5c7bea9aa6cee73ccb23d5b9","name":"lisi","pwd":"very good"}
**********************    after update many end
**********************    after delet one start
{"_id":"5c7bea9aa6cee73ccb23d5b8","name":"zhangsan","pwd":"very good"}
{"_id":"5c7bea9aa6cee73ccb23d5b9","name":"lisi","pwd":"very good"}
**********************    after delet one end
**********************    after delet many start
**********************    after delet many end

对应test.js文件中的代码看看日志的内容就可以看到每一行代码对数据库中内容的影响。

相关文章

网友评论

      本文标题:3.MongoDB配置与基础使用

      本文链接:https://www.haomeiwen.com/subject/vprmuqtx.html