Share mongoDB instance in multiple modules using Express [duplicate] - node.js

This question already has answers here:
Setting up singleton connection with node.js and mongo
(5 answers)
Closed 5 years ago.
I new to express. Now i am working in mongodb connection and CRUD activity. I created a connection in connection.js. And i get the database instance in app.js. The same DB instance i need to share register, login and some other modules without calling connection.js in these modules again. Or i need the proper answer to resuse connection in multiple modules in express.
Thanks in Advance,

You can setup a db module like so:
// db.js
let _db;
module.exports = {
getDb,
initDb
};
function initDb(callback) {
//connect to db and set _db to the new connection.
}
function getDb() {
assert.ok(_db, "Db has not been initialized. Please called init first.");
return _db;
}
Then somewhere in your app initialization you can do:
//app.js
const dbmodule = require("./db.js");
initDb(function(err){
// more app init;
});
then in your other modules, say login.js, do:
//login.js
const dmModule = require("./db")
const db = dbModule.getDb() //at this point the db should have been initialized.

Related

Database Connection using common module is not working [ mongoose and mongodb ]

I am trying to implement a common module for MongoDB connection using mongoose. and want to use the connection in other application for database operation. but facing issue when trying to use common database module. operation is halted / hanging after creating db connection. here is my codebase.
When I am using module specific dababase connection, then it is working fine, but when I am using common database connection it is hanging
Common DB Module
'use strict'
const mongoose = require('mongoose');
const DBOptions = require('./DBOption');
require("dotenv").config();
mongoose.Promise = global.Promise;
let isConnected;
const connectToDatabase = (MONGODB_URL) => {
if (isConnected) {
console.log('using existing database connection');
return Promise.resolve();
}
console.log('using new database connection');
console.log('DBOptions >> '+JSON.stringify(DBOptions));
return mongoose.connect(MONGODB_URL, DBOptions)
.then(db => {
console.log('db.connections[0].readyState >> '+db.connections[0].readyState);
isConnected = db.connections[0].readyState;
});
};
module.exports = connectToDatabase;
API Controller
const dbConnection = require('../DB/connection') // Internal Class
const DBConnection = require('as-common-util').connectToDatabase; // Common Class
/**
*
*/
app.get('/usr/alluser', async (req, res) => {
try {
//await dbConnection(process.env.MONGODB_URL) // This is working
await DBConnection(process.env.MONGODB_URL) // Code is hanging for this
let allUsers = await UserService.getAllUser()
console.log("All Users >> " + allUsers)
if (allUsers) {
return res.status(200).send(
new APIResponse({
success: true,
obj: allUsers
})
)
}
} catch (error) {
console.log(error)
}
})
It is hanging at following position
using new database connection
DBOptions >>
{"useNewUrlParser":true,"useUnifiedTopology":true,"useCreateIndex":true,"useFindAndModify":false,"autoIndex":false,"poolSize":10,"serverSelectionTimeoutMS":5000,"socketTimeoutMS":45000,"family":4}
db.connections[0].readyState >> 1
I am confused why same code is not working for common module.
This kind of pattern is not how Mongoose is meant to be used. Under the hood, Mongoose passes the underlying connection to the models in your module without the user really knowing anything about what is going on. That's why you can do magic stuff like MyModel.find() without ever having to create a model object yourself, or pass a db connection object to it.
If your db connection is in another module though, Mongoose won't be able to make those connections between your models and the MongoDB client connection since the models are no longer being registered on the mongoose object that is actually connected, and as a result, any requests you make using your models will break, since they will always be trying to connect through the object in your module.
There are other reasons why this won't, and shouldn't, work though. You're not supposed to be able to split a client. Doing so would make it unclear where communication along a client is coming from, or going to. You could change your function to make it return an established client connection. But your Mongoose models still wouldn't work. You would just be left with raw mongodb. If you want to do that, you might as well just uninstall Mongoose and use the mongodb library. Ultimately, you don't really gain anything from initializing the connection in a shared module. Initializing a connection is just a couple lines of code.
I doubt it's the connection that you want to share, rather it's the models (I'm guessing). You can put those in a shared module, and export them as a kind of connector function that injects the a given Mongoose instance into the models. See: Defining Mongoose Models in Separate Module.

Create Bookshelf.js models without connection and make connection in route files

I have Bookshelf.js models (a general model with parse() and format() functions and a model for each table that extends the general model) and routes that use these models. The database is PostgreSQL. But I have users in a SQLite database and each user has its own PostgreSQL connection options. I can retrieve the current user and expose its database connection options in the request, so every route knows how to connect to PostgreSQL. But how can I connect and use my Bookshelf.js models in a route? This is an example of what I am trying to do in a routes file:
var express = require('express'),
knex = require('knex'),
// This should be the file that exposes all models.
// Every model exposed, extends the general model.
// But it already requires a connection when init Bookshelf.js...
dataBookshelf = require('../models'),
router = express.Router();
router.get('/items/:id',function(req,res,next) {
// In req.db I have PostgreSQL connection options for the current user.
var connection = req.db;
// Make a connection to PostgreSQL.
var db = dataBookshelf(knex(connection));
// Use Items model.
var Items = db.Items;
Items.read(req.params.id).then(function(item) {
res.json(item);
}).catch(Items.NotFoundError,function() {
var err = new Error('Item not found.');
res.status(400).json(err);
});
});
module.exports = router;
If there is another way to save the current user connection options globally and to use them in the module that exposes Bookshelf.js instance, instead of passing them in the request, it should be better and safer.

mongoose connection as a separate module in nodejs app

In my project I want to make a separate module to get mongoose connection,say connection.js ,
var mongoose = require('mongoose');
mongoose.connect('mongodb://host:port/db');
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection open to localhost:27017' );
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
});
module.exports= mongoose;
which I can import using require in another file,say file1.js , as
var connect_to_mongoose = require('connection');
whenever necessary.
But I have came across the problem that since in nodejs IO is async then how can i make sure that the connection is successful and I can now use connect_to_mongoose variable for queries,insertions,deletions etc.
My second question is that after handling the above scenario how can I manage multiple connections for multiple databases. Bcoz as far as i know(for practical reasons) in mongoose one connection is dedicated to one DB only.
I think you should consider scenarios while working with mongodb and mongoose.
mongoose.connect opens a default connection as soon as app starts
you don't have to create every time a new connection if you are dealing with multiple tables / collections (whatever you call).
if you are dealing with multiple databases then you've separate your mongodb url like mongoose.connect(mongodb://localhost/db1) && mongoose.connect(mongodb://localhost/db2)
But above point no. 3 would give you an Warning : Trying to Close an open connection
To solve above issue just use the following :
var db = mongoose.createConnection(mongodb://localhost/db1)
And after your all tasks are completed close the connection
Cheers :)

Create a connection to the mongodb if connection is not established

I am new to node.js and mongoose.
I am trying to check whether a database with supplied name exists or not,
if exists,
establish a connection and use the same.
if not,
then create database with some collections.
I am using mongoose, as mongoose is providing 3 methods to establish the connection. i am unable to figure out which is the best suite for me and how to deal with them.
connect
createConnection
connection
By googling i got succeed in figuring out whether the DB name exists or not using createConnection.
var Admin = mongoose.mongo.Admin;
var dbName='test';
/// create a connection to the DB
var connection = mongoose.createConnection('mongodb://localhost/' +dbName );
connection.on('open', function () {
// connection established
new Admin(connection.db).listDatabases(function (err, result) {
console.log('listDatabases succeeded');
for (var i in result.databases) {
if (result.databases[i].name == dbName) {
mongoose.connect('mongodb://localhost/' + dbName);
next();
break;
}
}
});
});
I wrote the above code in route interceptor, so for every request the above code will be executed and trying to connect to mongodb if the given db name already exists.
Any help would be greatly appreciable..

efficiency of mongodb/mongoskin access by multiple modules approach?

I'm developing an express app that provides a REST api, it uses mongodb through mongoskin. I wanted a layer that splits routing from db acess. I have seen an example that creates a database bridge by creating a module file, an example models/profiles.js:
var mongo = require('mongoskin'),
db = mongo.db('localhost:27017/profiler'),
profs = db.collection('profiles');
exports.examplefunction = function (info, cb) {
//code that acess the profs collection and do the query
}
later this module is required in the routing files.
My question is: If I use this aproach for creating one module for each collection, will it be efficient? Do I have an issue of connecting and disconnecting multiple(unnecessary) times from mongo by doing that?
I was thiking that maybe exporting the db variable from one module to the others that handle each collection would solve the suposed issue, but I'm not sure.
Use a single connection and then create your modules passing in the shared db instance. You want to avoid setting up separate db pools for each module. One of doing this is to construct the module as a class.
exports.build = function(db) {
return new MyClass(db);
}
var MyClass = function(db) {
this.db = db;
}
MyClass.doQuery = function() {
}

Resources