保持打开MongoDB数据库连接

Lew*_*Lew 63 mongodb node.js

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

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

如果MongoDB与任何其他数据库系统一样,open并且close操作通常在时间上是昂贵的.

所以,我的问题是:只需执行MongoClient.connect("...一次,将返回db值分配给某个全局模块,在模块中具有各种功能进行各种与数据库相关的工作(将文档插入集合,更新文档等等)即可.当它们被应用程序的其他部分调用时(从而重新使用该db值),然后,当应用程序完成时,才会执行close.

换句话说,open并且close只完成一次 - 不是每次你都需要去做一些与数据库相关的操作.而且,当你实际完成所有与数据库相关的工作时,你不断重复使用db在初始阶段返回的对象open\connect,只在最后处理它close.

显然,由于所有的I/O都是异步的,所以在close确定最后一个数据库操作完成之后才发出close.看起来这样应该没关系,但我想仔细检查,以防万一我错过了一些东西,因为我是MongoDB的新手.谢谢!

Pet*_*ons 50

是的,这是很好的典型行为.启动你的应用程序,连接到db,长时间对数据库执行操作,如果连接意外死亡,可能重新连接,然后永远不要关闭连接(只需依赖于进程死亡时自动关闭) .

  • 我按照解决方案/sf/answers/1724411811/执行了与此答案中提到的相同的操作.但是,如果连接意外死亡,我们如何自动重新连接? (6认同)
  • 此外,默认情况下,您使用node-mongodb-native获得5个池连接.查看[poolSize]上的文档(http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html#mongoclient-connect-options). (2认同)

Hen*_*hin 5

mongodb版本^ 3.1.8

初始化连接作为一个承诺:

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://...'
const client = new MongoClient(uri)
const connection = client.connect() // initialized connection
Run Code Online (Sandbox Code Playgroud)

然后,只要您希望对数据库执行操作,就调用该连接:

    // 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
        })
    })
Run Code Online (Sandbox Code Playgroud)

  • 代码示例使事情变得更加清晰,谢谢。 (2认同)
  • 解决 Promise 然后将 MongoClient 对象存储在 connect var 中,而不是每次访问 db 时都解决不是更好吗? (2认同)

小智 5

当前接受的答案是正确的,因为您可以保持相同的数据库连接打开以执行操作,但是,它缺少有关在连接关闭时如何重试连接的详细信息。以下是自动重新连接的两种方法。它是用 TypeScript 编写的,但如果需要,它可以轻松转换为普通的 Node.js。

方法1:MongoClient选项

允许 MongoDB 重新连接的最简单方法是在将 a 传入 时reconnectTries在 an 中定义 a 。任何时候 CRUD 操作超时,它都会使用传入的参数来决定如何重试(重新连接)。将选项设置为本质上使其永远重试,直到能够完成操作。如果您想查看会重试哪些错误,可以查看驱动程序源代码。optionsMongoClientMongoClientNumber.MAX_VALUE

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.');
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

方法2:Try-catch重试

如果您希望在尝试重新连接时获得更精细的支持,可以使用带有 while 循环的 try-catch。例如,您可能希望在必须重新连接时记录错误,或者您希望根据错误类型执行不同的操作。这还允许您根据更多条件重试,而不仅仅是驱动程序中包含的标准条件。该insert方法可以改为如下:

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
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)