zoukankan      html  css  js  c++  java
  • koa操作MongoDB数据库的封装

    解决原生NodeJS 操作MongoDB 数据库的性能问题,封装成更小、更灵活的操作MongoDB库:

    Config.js 将所要连接的数据的配置信息封装成一个模块:

    const Config = {
        dbUrl:'mongodb://admin:123@localhost:27017/',
        dbName:'hello'
    }
    module.exports=Config;
    

    封装数据库时,引入数据库配置模块就好,首先通过 promise 封装:

    const MongoClient = require('mongodb').MongoClient;
    const Config = require('./config.js');
    
    class Db {
        constructor() {
    
        }
        //连接数据库
        connect() {  
           console.time('time_connect')
           return new Promise((resolve, reject) => {
               MongoClient.connect(Config.dbUrl, { useUnifiedTopology: true },(err, client) => {
                   if (err) {
                       console.log("连接数据库失败")
                       reject(err)
                       return
                   }
                   const db = client.db(Config.dbName);
                   console.log("连接数据库成功")
                   console.timeEnd('time_connect')
                   resolve(db)
               })
           })
        }
        //查询数据
        find(collectionName, json) {
            return new Promise((resolve, reject) => {
                this.connect().then((db) => { //连接数据库返回的db对象
                    db.collection(collectionName).find(json).toArray(function (err, result) {
                        if (err) {
                            reject(err);
                            return;
                        }
                        resolve(result);
                    })
                })
            })
        }
    }
    
    console.time('time_find1')
    const myDb1 = new Db()
    myDb1.find('user', {}).then(data=> { //find返回的是promise
        console.log("查询数据1");
        console.timeEnd('time_find1')
    })
    
    console.time('time_find2')
    const myDb2 = new Db()
    myDb2.find('user', {"name":"jack3"}).then(data => { //find返回的是promise
        console.log("查询数据2");
        console.timeEnd('time_find2')
    })
    
    /**
     * 连接数据库成功
     * time_connect: 49.488ms
     *  连接数据库成功
     * (node:12552) Warning: No such label 'time_connect' for console.timeEnd()
     * 查询数据1
     * time_find1: 65.757ms
     * 查询数据2
     * time_find2: 53.866ms
     */
    

    发生了两个问题,一是每次查询都需要连接数据库(查询时连接数据库获得 client 对象 ),而是每次查询都需要重新创建一个实例(myDb1,myDb2 )

    首先解决多次连接数据库的问题:

    可以在构造函数中定义一个 dbClient 的属性,通过这个属性值判断是否成功连接了数据库:

    测试:

    const MongoClient = require('mongodb').MongoClient;
    const Config = require('./config.js');
    
    class Db {
        constructor() {
            this.dbClient="";
        }
        //连接数据库
        connect() {  
            console.time('time_connect')
            return new Promise((resolve, reject) => {
                if(!this.dbClient){
                    MongoClient.connect(Config.dbUrl, { useUnifiedTopology: true }, (err, client) => {
                        if (err) {
                            console.log("连接数据库失败")
                            reject(err)
                            return
                        }
                        this.dbClient = client.db(Config.dbName);
                        console.log("连接数据库成功")
                        console.timeEnd('time_connect')
                        resolve(this.dbClient)
                    })
                }
                else{
                    resolve(this.dbClient)
                }
                
            })
        }
        //查询数据
        find(collectionName, json) {
            return new Promise((resolve, reject) => {
                this.connect().then(db => { //连接数据库连接返回的db对象
                    db.collection(collectionName).find(json).toArray(function (err, result) {
                        if (err) {
                            reject(err);
                            return;
                        }
                        resolve(result);
                    })
                })
            })
        }
    }
    
    const myDb = new Db()
    
    console.time('time_find1')
    myDb.find('user', {}).then(data => { 
        console.log("查询数据1");
        console.timeEnd('time_find1')
    })
    setTimeout(()=>{
        console.time('time_find2')
        myDb.find('user', {}).then(data => {
            console.log("查询数据2");
            console.timeEnd('time_find2')
        })
    },3000)
    
    
    /**
     * 连接数据库成功
     * time_connect: 47.374ms
     * 查询数据1
     *  time_find1: 70.183ms
     * 查询数据2
     * time_find2: 2.112ms
     */
    

    但是多次实例化时,dbClient 重新为"",还是会再次去连接数据库:

    const MongoClient = require('mongodb').MongoClient;
    const Config = require('./config.js');
    
    class Db {
        constructor() {
            this.dbClient="";
        }
        //连接数据库
        connect() {  
            console.time('time_connect')
            return new Promise((resolve, reject) => {
                if(!this.dbClient){
                    MongoClient.connect(Config.dbUrl, { useUnifiedTopology: true }, (err, client) => {
                        if (err) {
                            console.log("连接数据库失败")
                            reject(err)
                            return
                        }
                        this.dbClient = client.db(Config.dbName);
                        console.log("连接数据库成功")
                        console.timeEnd('time_connect')
                        resolve(this.dbClient)
                    })
                }
                else{
                    resolve(this.dbClient)
                }
                
            })
        }
        //查询数据
        find(collectionName, json) {
            return new Promise((resolve, reject) => {
                this.connect().then(db => { //连接数据库连接返回的db对象
                    db.collection(collectionName).find(json).toArray(function (err, result) {
                        if (err) {
                            reject(err);
                            return;
                        }
                        resolve(result);
                    })
                })
            })
        }
    }
    
    const myDb1 = new Db()
    console.time('time_find1')
    myDb1.find('user', {}).then(data => { 
        console.log("查询数据1");
        console.timeEnd('time_find1')
    })
    
    const myDb2 = new Db()
    setTimeout(()=>{
        console.time('time_find2')
        myDb2.find('user', { "name": "jack5" }).then(data => {
            console.log("查询数据2");
            console.timeEnd('time_find2')
        })
    },2000)
    /**
     * 连接数据库成功
     * time_connect: 42.574ms
     * 查询数据1
     * time_find1: 55.639ms
     * 连接数据库成功
     * time_connect: 5.675ms
     * 查询数据2
     * time_find2: 16.233ms
     */
    

    通过单例模式解决这个问题:

    const MongoClient = require('mongodb').MongoClient;
    const Config = require('./config.js');
    
    class Db {
        static getInstance(){
            if (!Db.instance) { //单例  解决多次实例化实例不共享的问题
                Db.instance=new Db()
            }
            return Db.instance
        }
        constructor() {
            this.dbClient="";
        }
        //连接数据库
        connect() {  
            console.time('time_connect')
            return new Promise((resolve, reject) => {
                if (!this.dbClient) { //解决数据库多次连接的问题
                    MongoClient.connect(Config.dbUrl, { useUnifiedTopology: true }, (err, client) => {
                        if (err) {
                            console.log("连接数据库失败")
                            reject(err)
                            return
                        }
                        this.dbClient = client.db(Config.dbName);
                        console.log("连接数据库成功")
                        console.timeEnd('time_connect')
                        resolve(this.dbClient)
                    })
                }
                else{
                    resolve(this.dbClient)
                }
                
            })
        }
        //查询数据
        find(collectionName, json) {
            return new Promise((resolve, reject) => {
                this.connect().then(db => { //连接数据库连接返回的db对象
                    db.collection(collectionName).find(json).toArray(function (err, result) {
                        if (err) {
                            reject(err);
                            return;
                        }
                        resolve(result);
                    })
                })
            })
        }
    }
    
    const myDb1 = Db.getInstance() //相当于 myDb1 = new Db()
    console.time('time_find1')
    myDb1.find('user', {}).then(data => { 
        console.log("查询数据1");
        console.timeEnd('time_find1')
    })
    
    const myDb2 = Db.getInstance() //相当于 myDb2 = Db.instance
    setTimeout(()=>{
        console.time('time_find2')
        myDb2.find('user', { "name": "jack5" }).then(data => {
            console.log("查询数据2");
            console.timeEnd('time_find2')
        })
    },2000)
    
    /**
     * 连接数据库成功
     * time_connect: 41.880ms
     * 查询数据1
     * time_find1: 55.679ms
     * 查询数据2
     *  time_find2: 2.045ms
     */
    

    最后封装好的 db库将它暴露出去,这里还可以在初始化的时候就连接数据库,第一次操作数据库在初始化就连接上,而不是执行具体操作的时候连接数据库:

    const MongoClient = require('mongodb').MongoClient;
    const Config = require('./config.js');
    
    class Db {
        static getInstance() {
            if (!Db.instance) { //单例  解决多次实例化实例不共享的问题
                Db.instance = new Db()
            }
            return Db.instance
        }
        constructor() {
            this.dbClient = "";
            this.connect()
        }
        //连接数据库
        connect() {
            //console.time('time_connect')
            return new Promise((resolve, reject) => {
                if (!this.dbClient) { //解决数据库多次连接的问题
                    MongoClient.connect(Config.dbUrl, { useUnifiedTopology: true }, (err, client) => {
                        if (err) {
                            console.log("连接数据库失败")
                            reject(err)
                            return
                        }
                        this.dbClient = client.db(Config.dbName);
                        console.log("连接数据库成功")
                        //console.timeEnd('time_connect')
                        resolve(this.dbClient)
                    })
                }
                else {
                    resolve(this.dbClient)
                }
    
            })
        }
        //查询数据
        find(collectionName, json) {
            return new Promise((resolve, reject) => {
                this.connect().then(db => { //连接数据库连接返回的db对象
                    db.collection(collectionName).find(json).toArray(function (err, result) {
                        if (err) {
                            reject(err);
                            return;
                        }
                        resolve(result);
                    })
                })
            })
        }
        //修改数据(一条)
        update(collectionName, oldData, newData) {
            return new Promise((resolve, reject) => {
                this.connect().then((db) => {
                    db.collection(collectionName).updateOne(oldData, { $set: newData }, (err, result) => {
                        if (err) {
                            console.log("修改数据失败")
                            reject(err)
                            return;
                        }
                        console.log("修改数据成功")
                        resolve(result)
                    })
                })
            })
        }
        //添加数据(一条)
        insert(collectionName, addData) {
            return new Promise((resolve, reject) => {
                this.connect().then(db => {
                    db.collection(collectionName).insertOne(addData, (err, result) => {
                        if (err) {
                            console.log("添加数据失败")
                            reject(err)
                            return
                        }
                        console.log("添加数据成功")
                        resolve(result)
                    })
                })
            })
        }
        //删除数据(一条)
        remove(collectionName, deleteData) {
            return new Promise((resolve, reject) => {
                this.connect().then(db => {
                    db.collection(collectionName).removeOne(deleteData, (err, result) => {
                        if (err) {
                            console.log("删除数据失败")
                            reject(err)
                            return
                        }
                        console.log("删除数据成功")
                        resolve(result)
                    })
                })
            })
        }
    
    }
    
    module.exports = Db.getInstance()

     引入封装好的 db 库,通过 kob 操作:

    const Koa = require('koa')
    const app = new Koa()
    const router = require('koa-router')()
    const render = require('koa-art-template')
    const views = require('koa-views')
    const path = require('path')
    const Db = require('./util/db')
    
    //配置art-template
    render(app, {
        root: path.join(__dirname, 'views'),   // 视图的位置
        extname: '.html',  // 后缀名
        debug: process.env.NODE_ENV !== 'production'  //是否开启调试模式
    })
    
    router.get('/', async (ctx)=>{
        let res = await Db.find('user', { "name": "李华" })
        //console.log(res) //{ _id: 5eef338f7701003ebcbbafa3, name: '李华', age: 18 }
        await ctx.render('index', {
            name: res[0].name,
            age: res[0].age
        }) 
    })
    
    
    
    app.use(router.routes());   
    app.use(router.allowedMethods());
    app.listen(3000);
    

  • 相关阅读:
    C# winform中 窗体缩放自适应的方法(不同电脑/不同分辨率)
    C# WinForm窗体及其控件自适应各种屏幕分辨率
    Socket网络编程
    C# Socket编程
    获取当前程序目录
    C# winfrom界面跳转闪烁问题解决方法
    C# 屏蔽windows功能键
    c#多线程调用有参数的方法
    C# winform Visual Studio Installer打包教程
    查询重复的数据
  • 原文地址:https://www.cnblogs.com/shanlu0000/p/13179112.html
Copyright © 2011-2022 走看看