简体   繁体   中英

What is the correct way to make MongoDB Atlas connection available in middleware functions in Node.js/Express?

Environment

Node.js ( 18 LTS ) / Express ( ^4.18.2 )
MongoDB Native Driver ( ^4.12.0 )
MongoDB Atlas ( 5.0.14 )

Application Structure

.github  
config  
 - mongodb_client.js  
dist  
middleware  
node_modules  
routes  
src
views
.env  
.gitignore
app.js  
package.json  
README.md  

Connection Code

As a sanity check, this is the connection code that is provided in the MongoDB Atlas interface:

As a screenshot:
在此处输入图像描述

As code:

const { MongoClient, ServerApiVersion } = require('mongodb');

const uri = "mongodb+srv://admin:<password>@cluster0.******.mongodb.net/?retryWrites=true&w=majority";

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

client.connect(err => {
  const collection = client.db("test").collection("devices");
  // perform actions on the collection object
  client.close();
});

Desired Behaviour

The code snippet provided in the MongoDB Atlas interface performs the connection and subsequent database calls in one file.

However, I would like to:

  • Create a file that contains the MongoDB Atlas connection (eg mongodb_client.js )
  • Export the connection so that it can be used in middleware files (eg my_middleware_01.js )

So, in pseudo code, I imagine it would look something like this:

config / mongodb_client.js

import { MongoClient, ServerApiVersion } from 'mongodb'; 

const connection_string = process.env.MONGODB_CONNECTION_STRING;

const mongodb_client = new MongoClient(connection_string, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });

// export the connection somehow   
export { mongodb_client };

middleware / my_middleware_01.js

import { mongodb_client } from '../config/mongodb_client.js';

const api_myResource_get = async (req, res) => {
    mongodb_client.open();
    let collection = mongodb_client.db('myDatabase').collection('myCollection');
    let result = await collection.findOne(query, options);  
    res.json({ result: result });
    mongodb_client.close();  
}; 

export { api_myResource_get };

What I've Tried

It seems I was grappling with this dynamic over a year ago and posted my solution here:

https://stackoverflow.com/a/70135909

However, I think that conventions have changed since then.

For example when instantiating the client, the current method seems to be:

const client = new MongoClient(connection_string, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });

whereas previously it was something like:

await MongoClient.connect(connection_string);

I've Google searched:

how to make mongodb connection available in node.js middleware?

But all the results seem to reference this older convention and I'd like to ensure I am using best practice (and most recent conventions).

Related Questions and Resources

Passing Mongo DB Object DB to Express Middleware

What is best way to handle global connection of Mongodb in NodeJs

How do I manage MongoDB connections in a Node.js web application?

What is the difference between MongoClient and the client object which we get in the callback of MongoClient.connect() method

How to properly reuse connection to Mongodb across NodeJs application and modules

MongoDB Driver Connection Documentation

EDIT 01:

Below is one attempt which is returning the error:

TypeError: Cannot read properties of null (reading 'db')

config / mongodb_connection.js

import { MongoClient, ServerApiVersion } from 'mongodb'; 

const connection_string = process.env.MONGODB_CONNECTION_STRING;

class mongodb_connection {
  static async open() {
    if (this.conn) return this.conn;
    this.conn = await MongoClient.connect(connection_string, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });
    return this.conn;
  }
}

mongodb_connection.conn = null;
mongodb_connection.url = connection_string;

export { mongodb_connection };

middleware / api_mongodb_get.js

import { mongodb_connection } from '../../config/mongodb_connection.js';

const api_mongodb_get = async (req, res) => {

    try {
        mongodb_connection.open();
        const collection = mongodb_connection.conn.db('pages').collection('pages');
        const result = await collection.findOne({ "my_key": "my value" }); 

        res.json({ data: result });
        mongodb_connection.close();
    } catch (error) {
        console.error(error);
        res.status(500).send(error);
    }

};

export { api_mongodb_get };

EDIT 02:

The following 'works' but I don't know if it is best practice or not.

In other words, I don't know if I am overlooking something that will cause undesired behavior.

config / mongodb_connection.js

import { MongoClient, ServerApiVersion } from 'mongodb'; 

const connection_string = process.env.MONGODB_CONNECTION_STRING;

const mongodb_connection = new MongoClient(connection_string, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });

export { mongodb_connection };

middleware / api_mongodb_get.js

import { mongodb_connection } from '../../config/mongodb_connection.js';

const api_mongodb_get = async (req, res) => {

    try {
            mongodb_connection.connect(async err => {  

                const collection = mongodb_connection.db('pages').collection('pages');
                const result = await collection.findOne({ "my_key": "my value" }); 

                res.json({ data: result });
                
                mongodb_connection.close();
            });
    } catch (error) {
        console.error(error);
        res.status(500).send(error);
    }

};

export { api_mongodb_get };

Insetead of using mongodb , use mongoose library to establish the connection. Here is an example to establish the connection with mongodb cluster:

connectDb.js:


const dotenv = require('dotenv').config();
const DB_URL = process.env.DB_URL;
const mongoose = require('mongoose');

const connectDb = async () => {
    try {
        const connection = await mongoose.connect(DB_URL)
        console.log(`Connected to database Successfully: ${connection}`)
    } catch (error) {
        console.log(error)
    }
}
module.exports = connectDb;

and I think I don't need to mention that the DB_URL is the URL which is provided by the mondodb cluster.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM