如何在NodeJS中维护mongo客户端

时间:2020-10-20 10:08:18

标签: node.js mongodb express connection

我试图了解如何在节点应用程序中维护mongo客户端。我首先想到的是在每个单个集合检索上创建一个客户端。像这样:

const getCollection = (collectionName) => {
return MongoClient.connect(url, {useNewUrlParser: true, useUnifiedTopology: true})
    .then((client) => {
        const database = client.db(databaseName);
        return database.collection(collectionName);
    })
    .catch((err) => {
        console.log(err);
    });
};

然后将返回的promise用于查询。像这样:

const executeFind = (collectionName, query, projection, skip, limit) => {
    return getCollection(collectionName)
        .then(collection => {
            return collection.find(query, {projection: projection})
                .skip(skip)
                .limit(limit)
                .toArray();
        })
        .catch((err) => {
            console.log(err);
        });
};

这种方法的问题是,在运行应用程序时,与mongo的打开连接的数量迅速增加,从而导致数据库操作和大量警报出现问题。

我认为连接增加的可能原因:

  • 大型池大小-我尝试将maxPoolSize=5添加到URL。还向poolSize: 5添加options MongoClient connect函数的第二个参数。连接数仍会中断。
  • 缺少连接,请关闭-我现在找不到文档,但是我读到某处连接由客户端本身管理,因此无需考虑close()进行连接。但是无论如何,在close()返回结果之后,我试图将代码重写为collection.find()客户端。我得到Cannot use a session that has ended

除了这些之外,我没有其他想法可以以一种在资源分配/运行方面高效的方式来维护mongo客户端。我想听到两个答案:

  • 1。为了避免开放连接增加,这种方法到底可以做什么?
  • 2。维护mongo客户的更一般/最佳/最佳实践方法是什么。

2 个答案:

答案 0 :(得分:0)

  • 检查下面的代码片段以了解mongo数据库池连接。

MongoClient.connect(url, {
  poolSize: 10
  // other options can go here
}, function(err, db) {
  global.mongodb = db;
});

  • 要处理连接,我们需要编写自定义代码,例如检查连接是否存在,如果不创建新连接。

答案 1 :(得分:0)

我可以部分回答我的问题。 我可以使用client.close()解决连接增加的问题。主要问题似乎是承诺没有兑现await,因此close()导致了意外的行为(close()有时在实际调用查询之前发生,并导致{{1} }错误)。

上述方法(每次通话都打开和关闭连接)的问题在于速度很慢。

仍在寻找有关最佳维护客户的一般答案。

更新

我终于找到了一种解决方案,该解决方案不会大量打开连接,而且效果最佳。

此处的技巧是在将设置数据库对象的数据访问层(或数据库代码所在的位置)中声明并调用异步函数。像这样:

session already closed

然后只需在各处重用数据库对象,就像这样:

let database;

(async () => {
    const client = await MongoClient.connect(url, {poolSize: 150, useNewUrlParser: true, useUnifiedTopology: true});
    database = client.db(databaseName);
})();

池和连接的打开/关闭由database.collection(collectionName).insertMany(documents); 处理。就最佳性而言,它的速度更快(如预期)。不确定是否可以在dao中调用全局数据库或立即函数(不过,由于文件是通过client导入的,因此不应多次调用)是最佳实践,但确实可以解决问题。

相关问题