保持打开 MongoDB 数据库连接

在许多使用 MongoDB 的介绍性示例中,您可以看到如下代码:

var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:port/adatabase", function(err, db)
{
/* Some operation... CRUD, etc. */
db.close();
});

如果 MongoDB 像任何其他数据库系统一样,那么 openclose操作通常在时间上都很昂贵。

因此,我的问题是: 是否可以简单地执行一次 MongoClient.connect("...,将返回的 db值分配给某个模块全局,让模块中的各个函数在应用程序的其他部分调用它们时执行各种与数据库相关的工作(将文档插入集合、更新文档等)(从而重用该 db值) ,然后,当应用程序完成时,才执行 close

换句话说,openclose只完成一次——而不是每次您需要去做一些与数据库相关的操作时。并且您将不断重用在初始 open\connect期间返回的 db对象,只是在最后使用 close释放它,而实际上您已经完成了所有与数据库相关的工作。

显然,因为所有的 I/O 都是异步的,所以在发出 close之前,您要确保最后一个数据库操作在发出 close之前完成。看起来应该没问题,但我想再检查一下,以防我错过了一些东西,因为我是新的 MongoDB。谢谢!

23589 次浏览

Yes, that is fine and typical behavior. start your app, connect to db, do operations against the db for a long time, maybe re-connect if the connection ever dies unexpectedly, and then just never close the connection (just rely on the automatic close that happens when your process dies).

mongodb version ^3.1.8

Initialize the connection as a promise:

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://...'
const client = new MongoClient(uri)
const connection = client.connect() // initialized connection

And then call the connection whenever you wish you perform an action on the database:

    // if I want to insert into the database...
const connect = connection
connect.then(() => {
const doc = { id: 3 }
const db = client.db('database_name')
const coll = db.collection('collection_name')
coll.insertOne(doc, (err, result) => {
if(err) throw err
})
})

The current accepted answer is correct in that you may keep the same database connection open to perform operations, however, it is missing details on how you can retry to connect if it closes. Below are two ways to automatically reconnect. It's in TypeScript, but it can easily be translated into normal Node.js if you need to.

Method 1: MongoClient Options

The most simple way to allow MongoDB to reconnect is to define a reconnectTries in an options when passing it into MongoClient. Any time a CRUD operation times out, it will use the parameters passed into MongoClient to decide how to retry (reconnect). Setting the option to Number.MAX_VALUE essentially makes it so that it retries forever until it's able to complete the operation. You can check out the driver source code if you want to see what errors will be retried.

class MongoDB {
private db: Db;


constructor() {
this.connectToMongoDB();
}


async connectToMongoDB() {
const options: MongoClientOptions = {
reconnectInterval: 1000,
reconnectTries: Number.MAX_VALUE
};


try {
const client = new MongoClient('uri-goes-here', options);
await client.connect();
this.db = client.db('dbname');
} catch (err) {
console.error(err, 'MongoDB connection failed.');
}
}


async insert(doc: any) {
if (this.db) {
try {
await this.db.collection('collection').insertOne(doc);
} catch (err) {
console.error(err, 'Something went wrong.');
}
}
}
}

Method 2: Try-catch Retry

If you want more granular support on trying to reconnect, you can use a try-catch with a while loop. For example, you may want to log an error when it has to reconnect or you want to do different things based on the type of error. This will also allow you to retry depending on more conditions than just the standard ones included with the driver. The insert method can be changed to the following:

async insert(doc: any) {
if (this.db) {
let isInserted = false;


while (isInserted === false) {
try {
await this.db.collection('collection').insertOne(doc);
isInserted = true;
} catch (err) {
// Add custom error handling if desired
console.error(err, 'Attempting to retry insert.');


try {
await this.connectToMongoDB();
} catch {
// Do something if this fails as well
}
}
}
}
}