4

My goal is to set up an express based api with node.js using mongodb version 4.0 and node.js driver 3.1.10.
At the current stage my part of the api is basically done but eventually my collegues will merge their progress on to it. So my question is:
How can I share my connection instance of mongodb to acces it across multiple methods?

My current structure is of this type:

  • app.js server that calls route.js for routes managing
  • route.js that calls userController.js for mangaing user conecerned methods
  • userController.js that manages CRUD operations on resource /users

Searching on the web resulted that is recommended to keep a connection open so the nodejs driver will mange it for all queries, so what part of the connection I have to expose:

  • the result of the MongoClient.connect(url) callback?
  • the MongoClient.connect(url) value itself?

And when and where I have to open the connection and do I have to close it?

I know that some similar questions exists but they are old and refer to mongodb api and javscript implementations that are old too, so with the use of callbacks or awaits how can I achieve this?

2 Answers 2

2

You don't have to create a module now. Express has a built in feature to share data between routes. There is an object called app.locals. We can attach properties to it and access it from inside our routes. You simply instantiate your mongo connection in your app.js file.

var app = express();

MongoClient.connect('mongodb://localhost:27017/')
.then(client =>{
  const db = client.db('your-db');
  const collection = db.collection('your-collection');
  app.locals.collection = collection;
});
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // view engine setup
app.set('views', path.join(__dirname, 'views'));

This database connection can now be accessed within your routes as below without the need for creating and requiring additional modules.

app.get('/', (req, res) => {
  const collection = req.app.locals.collection;
  collection.find({}).toArray()
  .then(response => res.status(200).json(response))
  .catch(error => console.error(error));
});

This method ensures that you have a database connection open for the duration of your app unless you choose to close it at any time. It's easily accessible with req.app.locals.your-collection and doesn't require additional modules.

Sign up to request clarification or add additional context in comments.

1 Comment

in the example above, the MongoClient.connect() block seems to 'hardcode' the database name and collection name into app.locals. this is no good if you need to make calls to different databases and collections within the same route or across multiple routes. is there a way for app.locals to just store the client so that you could later query a specific database and collection?
1

You have to create a module, that exports the connection object created by the MongoClient.connect method. The problem here is that the method is asynchronous, so you have to handle it. You have multiple choices. One way could be this:

database.js

const MongoClient = require('mongodb').MongoClient
let url = 'mongodb://xxx'
let connection

module.exports = function() {
   return new Promise((resolve, reject) => {
      if (connection)
         resolve(connection)
      MongoClient.connect(url, (err, db) => {
         if (err)
            reject(err)
         connection = db
         resolve(connection) 
      })
   })
}

another module

var getMongoDbConnection = require('./database.js')

getMongoDbConnection()
.then((db) => {
    // your connection object
})
.catch((e) => {
    // handle err
})

// or inside an async method
app.get('/middleware' => async function(req, res, next) => {
    try {
       let db = await getMongoDbConnection()
    } catch (e) {
      // handle
    }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.