MongoError: Topology is closed, please connect (client.close and client.connect issue)

MongoError: Topology is closed, please connect (client.close and client.connect issue)

(node:21140) UnhandledPromiseRejectionWarning: MongoError: Topology is closed, please connect

我认为是在CRUD操作的每个函数中重复client.connect和client.close的错误,如下代码所示

//我认为集群 uri 没有问题所以我没有 post 因为它连接正常

const MongoClient = require("mongodb").MongoClient;

const uri = "mongodb+srv://username:pasword@some cluster"; 
//I think there is no issue with cluster uri so I didn't post that since it connects fine


const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });



async function AddnewService(service) {
    await client.connect()
    const database = client.db("twitch")
   const usr = await database.collection("recipes").find({ Title: service.Title }).toArray()
    if (usr.length >= 1) {
        await client.close()
        return { message: "Title already in use" }
    }
    else {
        const result = await database.collection("recipes").insertOne(service)
        await client.close()
        return { message: "Service Added to Database" }
    }
}

async function FetchAllserviceSearch(service) {
    await client.connect()
    const database = client.db("twitch")
    let recipesCursor = await database.collection("recipes").find({})
    while (await recipesCursor.hasNext()) {                       //make sure to put await on cursor .hasnext()
        let recipe = await recipesCursor.next()
        console.log(recipe)
    }
    await client.close()

    return { message: "User Added to Database" }
}


module.exports = {
    AddnewService,
    FetchAllserviceSearch
}

我试着分配让 client.connect 和 client.close 只被调用一次,但它总是会导致新的错误。 我无法消除 module.export 因为我需要它们在其他文件中使用。

所以我需要一些帮助来解决一些问题,而不是因为 mongodbAtlas 导致的问题而进行不必要的重复。

不要关闭您的数据库连接,您处于竞争状态,当两个请求到来时,一个将关闭另一个将打开。

client.close(); -----> remove

对所有请求使用相同的数据库连接。

const uri = "mongodb+srv://username:pasword@cluster0.ik1pu.mongodb.net/myFirstDatabase?retryWrites=true&w=majority";

let con;

async function connect(service) {
   if (con) return con; // return connection if already conncted
   const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
   con = client.connect()
   return con;
}


async function AddnewService(service) {
    const client = await connect();
    const database = client.db("twitch")
    const usr = await database.collection("recipes").find({ Title: service.Title }).toArray()
    if (usr.length >= 1) {
        // await client.close(); -----> remove
        return { message: "Title already in use" }
    }
    else {
        const result = await database.collection("recipes").insertOne(service)
        return { message: "Service Added to Database" }
    }
}

async function FetchAllserviceSearch(service) {
    const client = await connect();
    const database = client.db("twitch")
    let recipesCursor = await database.collection("recipes").find({})
    while (await recipesCursor.hasNext()) {                       //make sure to put await on cursor .hasnext()
        let recipe = await recipesCursor.next()
        console.log(recipe)
    }
    // await client.close(); -----> remove
    return { message: "User Added to Database" }
}


module.exports = {
    AddnewService,
    FetchAllserviceSearch
}

您正在尝试关闭请求处理程序中的客户端,但您的客户端是全局的。

如果你想要一个全局客户端,请不要在请求处理程序中关闭它。

如果要关闭请求处理程序中的客户端,请在同一请求的处理程序中创建客户端。

创建一个连接class 来管理应用程序数据库连接。 MongoClient 不提供单例连接池,因此您不想在您的应用程序中重复调用 MongoClient.connect()。包装 mongo 客户端的单例 class 适用于我见过的大多数应用程序。

    const MongoClient = require('mongodb').MongoClient

    class Connection {
    
        static async open() {
            if (this.db) return this.db
            this.db = await MongoClient.connect(this.url, this.options)
            return this.db
        }
    
    }
    
    Connection.db = null
    Connection.url = 'mongodb://127.0.0.1:27017/test_db'
    Connection.options = {
        bufferMaxEntries:   0,
        reconnectTries:     5000,
        useNewUrlParser:    true,
        useUnifiedTopology: true,
    }
    
    module.exports = { Connection }

require('./Connection') 的任何地方,Connection.connectToMongo() 方法都可用,Connection.db 属性 如果已初始化,也将可用。

const { Connection } = require('../lib/Connection.js')

        async function AddnewService(service) {
        // This should go in the app/server setup, and waited for.
        await Connection.connectToMongo()
        const database = Connection.db("twitch")
       const usr = await database.collection("recipes").find({ Title: service.Title }).toArray()
        if (usr.length >= 1) {
           // await client.close()
            return { message: "Title already in use" }
        }
        else {
            const result = await database.collection("recipes").insertOne(service)
           // await client.close()
            return { message: "Service Added to Database" }
        }
    }

在 express 中你可以这样做,

import {MongoClient} from 'mongodb';
import express from 'express';
import bodyParser from 'body-parser';
    let mongoClient = null;
    MongoClient.connect(config.mongoURL, {useNewUrlParser: true, useUnifiedTopology: true},function (err, client) {
        if(err) {
          console.log('Mongo connection error');
        } else {
          console.log('Connected to mongo DB');
          mongoClient = client;
        }
    })
let app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.use((req,res,next)=>{
    req.db = mongoClient.db('customer_support');
    next();
});

并像这样在您的请求句柄中使用,

    router.post('/hello',async (req,res,next)=>{
    let uname = req.body.username;
    let userDetails = await AddnewService(req.db,uname) // change signature of this method
    res.statusCode = 200;
    res.data = userDetails;
    next();
});