有几个关于 mongodb 原生驱动的问题?
第一个,简单封装问题
// 连接数据库并选定集合然后返回
const { MongoClient } = require('mongodb');
const { db } = require('config-lite')(__dirname);
const { format } = require('url')
const _ = require('lodash')
const url = format(_.omit(db.mongodb, 'collection'));
/*
db.mongodb 类似
{
protocol: 'mongodb:',
hostname: '127.0.0.1',
slashes: true,
auth: null,
port: '27017',
pathname: '/xxxx',
collection: {
post: 'posts',
admin: 'admins',
}
*/
module.exports = function(collection, fieldOrSpec, options) {
return MongoClient.connect(url)
.then(db => {
return db.collection(collection)
})
.then(col => {
return !_.isUndefined(fieldOrSpec) && _.isPlainObject(fieldOrSpec)
? col.createIndex(fieldOrSpec, options)
.then((indexName) => {
return col
})
: col
})
};
// 增删查改操作,截取部分
const connect = require('./_connect_v2');
const isPlainObject = require('lodash/isPlainObject')
module.exports = {
count(collection, query, options) {
return isPlainObject(collection)
? connect(...Object.values(collection))
.then(col => {
return col.count(query, options)
})
: connect(collection)
.then(col => {
return col.count(query, options)
})
},
distinct(collection, key, query, options) {
return isPlainObject(collection)
? connect(...Object.values(collection))
.then(col => {
return col.distinct(key, query, options)
})
: connect(collection)
.then(col => {
return col.distinct(key, query, options)
})
},
insertOne(collection, data, options) {
return isPlainObject(collection)
? connect(...Object.values(collection))
.then(col => {
return col.insertOne(data, options)
})
: connect(collection)
.then(col => {
return col.insertOne(data, options)
})
}
}
不封装可能会有很长的链式操作,但是这样封装又会造成 没办法 db.close
,并且我也有几个疑惑:
第一个问题: MongoClient.connect 是每次都会创建一个拥有一定数量的连接池么?如果是这样那我只是单次数据库查询不是会很不高效,比如我只需要获得一个集合的文档总数
第二个问题: 查询资料的过程中有说 MongodbClient.connect 是维护了一个 100 个连接的连接池,也有人放官网图说是 改成了单例模式,我想问的就是到底是哪种(虽然第二种可能性很小)? 并且mongodb单例模式在 Nodejs 中的实现是否会有所不同,因为 Nodejs 表面单线程,底层还是多线程实现异步,总之我对这些知识很混乱,希望有人能讲一下。
额,你的表述性有些混乱,但基本问题我已了解; 首先、close或不close取决于你的项目需求,比如你是http的短连接请求,且请求量不大,那么每次close或许会(创建连接的代价也不小)高效些,但如果是长连接类聊天等高并发、实时性要求高的场景,长连接将是好的选择; 其次、创建一个connect连接或,默认情况下维护一个具有5个连接的连接池,你可以在本地shell打开一个终端,通过mongostat查看连接数,自己动手比什么都实在; 最后、连接池问题,你看下官方文档,在创建connect时有一个pool参数,默认是5个,这个大小可以自定义;
提问题要最小化,不然谁有空看那么长
@haozxuan 确实表述有些混乱,下次提问我会注意了。主要不太知道使用 promise 的时候,怎么让 mogodb 保持长连接呢?我对 mongodb 也并不是很了解,所以导致我也不知道怎么监控操作和连接状况。但是直到现在确实这个问题都困扰我,不封装 mongodb 原生驱动感觉有些时候比较累赘,链式可能写的很长。封装把就变成每次都需要 connect close 了,并且在 promise 中还难以传递 db 在操作之后 close,目前我是转到了 mongoose ,但是还是很想知道这个问题怎么处理?用代码表示就是:
// connect.js
const MongoClient = require('mongodb')
module.exports = MongoClient.connect
// db.js
const connect = require('./connect')
const url = require('../config').db.mongodb.url
module.exports = {
insertOne(collection, data) {
connect(url)
.then((db) => {
return db.collection(collection)
.insertOne(data)
})
/**
* 1. 想要达到的目标是长连接,但是在异步的情况下我不知道该怎么做
* 2. 退而求其次选择短连接,但是由于使用了 promise ,导致关闭变得困难
* 3. 于是我的问题变成了在不使用 async/await 的情况下仅用 promise 怎么处理这两种情况
*/
}
}
@leavesdrift 从你的第二次描述看,其实你并不关注关闭和创建带来的性能损耗,而是关注怎么优雅的用Promise进行易步流控制,目前我使用的是async,大致封装情况如下图,希望能够对你有所帮助: