I have been trying to make a web app using node.js and express and decided to work with mongodb. I am using mongodb node.js driver version: 4.3.1 I have tried all the possible ways to connect the node.js server with my mongodb atlas database.
My database also got connected using the following code in my db.js file:
const app = require('./app');
const MongoClient = require('mongodb').MongoClient
const Url = 'mongodb srv://todoAppUser:<myOriginalPasswordHere>@cluster0.6lvjr.mongodb.net/myDatabase?retryWrites=true&w=majority';
MongoClient.connect(Url, function (err, client) {
if (err) throw err;
var db = client.db('myDatabase');
db.collection('products').findOne({}, function (findErr, result) {
if (findErr) throw findErr;
console.log(result.name);
client.close();
});
});
The above code works fine and gives the output as well. But I want to use MVC (Model-view-Controller) framework for which I need to export the connection.
I made the following change in the above code:
MongoClient.connect(Url, function (err, client) {
if (err) throw err;
var db = client.db('myDatabase');
db.collection('products').findOne({}, function (findErr, result) {
if (findErr) throw findErr;
console.log(result.name);
module.exports = db
client.close();
});
});
After the change when I try to access my connection (const productCollection = require('./db').collection("product");) from any other file of mine, it gives me the following error:
const productCollection = require('./db').collection("product");
^
TypeError: require(...).collection is not a function
at Object.<anonymous> (D:\Kush- Complete Data\exp-projects\nodeApp\productController.js:1:43)
at Module._compile (internal/modules/cjs/loader.js:1072:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
at Module.load (internal/modules/cjs/loader.js:937:32)
at Function.Module._load (internal/modules/cjs/loader.js:778:12)
at Module.require (internal/modules/cjs/loader.js:961:19)
at require (internal/modules/cjs/helpers.js:92:18)
at Object.<anonymous> (D:\Kush- Complete Data\exp-projects\nodeApp\router.js:3:27)
at Module._compile (internal/modules/cjs/loader.js:1072:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
[nodemon] app crashed - waiting for file changes before starting...
May anyone please guide me and show a possible way out.
Thanks, Kush
CodePudding user response:
This can't work, because modules are evaluated synchronously. Your callback is called asynchronously but your module has been alread evaluated at this time. Means module.exports has no effect and require('./db').collection() is not defined. Please see Node.js Modules for details.
To solve your problem, handle the connection stored in a module internal variable and export a getter instead of the connection variable itself.
// db.js
let client;
let db;
function connectDB(url, dbName) {
client = new MongoClient(url);
return new Promise(function(resolve, reject) {
client.connect(function(err) {
if(err) return reject(err);
db = client.db(dbName);
return resolve(db);
});
});
}
function getCurrentDB() {
return db;
}
module.exports.connectDB = connectDB;
module.exports.getCurrentDB = getCurrentDB;
Then reuse your opened connection in other files like the following:
// other.js
const db = require("./db.js");
db.getCurrentDB().collection("product");
Of course, getCurrentDB() can only return a database connection if a connection has been established via connectDB() beforehand. So you have to wait for the resolution of the Promise.
CodePudding user response:
[SOLVED]
I figured out, in newer versions of mongodb they have essentially changed the way of connecting node server to the database.
To establish a reusable connection (So that we can access the connected database from any other file), I created an async function in my db.js file where connection is established and then exported it. In the end of the file, I have called the function.
The code is as follows:
const {MongoClient} = require('mongodb')
const client = new MongoClient('mongodb srv://todoAppUser:<password>@cluster0.6lvjr.mongodb.net/myDatabase?retryWrites=true&w=majority')
async function start(){
await client.connect()
console.log("Connected")
module.exports = client.db()
const app = require('./app')
app.listen(3000)
}
start()
and while calling it from another file:
const productCollection = require('./db').collection("product");
This code gives me no error and works perfectly fine. With the help of the above code, one can use this conveniently while following the MVC (Model-View-Controller) framework.
