mongoose connection as a separate module in nodejs app - node.js

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 :)

Related

next.js and mongodb coherence?

I googled a lot but still have no clear solution to my issue.
Connecting to MongoDB, usually you establish a connection and after the job is done you close it.
Since next.js (and probably node.js) is single threaded. Sometimes it happens that there are two requests processed async while one request established the connection to the database, the otherone is closing the exact same connection. So the first request runs into an Topology closed exception. I have the feeling that the mongodb driver client is shared.
Is there something I did not understood correct in this?
try {
await client.connect()
const database = client.db("test")
const collection = database.collection("test")
const newDataset = await collection.insertOne({})
return newDataset.insertedId.toString()
} finally {
await client.close();
}
As in the comments stated, ive seen a lot of examples & questions here on stackoverflow where in each received request (example below) a database connection is established. This has no benefits and is "bad" because it just takes time and makes no sense. E.g:
app.get("/", (req, res) => {
MongoClient.connect("...", (err, client) => {
// do what ever you want here
client.close();
});
});
If you application needs a database connection, establish the connection "in the startup phase" and keep the connection open. There is no reason to open and close the database connection for each request.
const mongodb = require("monogdb");
const express = require("express");
const app = express();
// some custom init stuff
// e.g. require your route handler etc.
mongodb.MongoClient("...", (err, client) => {
// do what ever you want with the db connection now
// e.g. monkey patch it, so you can use it in other files
// (There are better ways to handle that)
mongodb.client = client;
// or the better way
// pass it as function parameter
require("./routes")(app, client);
app.listen(8080, () => {
console.log("http server listening");
});
});
As you can see in the code above, we first create a database connection and then do other stuff. This has some advantages:
If your credentials are invalid, your application is not externeal reachable because the http server is not started
You have a single connection for all requests
Database queries are potential faster because you dont have to wait to establish first a db connection
NOTE: the code above was "inline coded" here and is not tested.
But i think its illustrated the concept behind my statement.

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 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..

Is it necessary to close mongodb connection in nodejs?

I'm new to nodejs and mongodb. in mongodb native driver website they close connection after each request but it seems like to be very slow and problematic in high traffic websites. I'm just curious to know is it necessary to do that or I can declare a global variable and reference that to DB like this:
var mongodbClient = require('mongodb').MongoClient;
var db;
function connect() {
mongodbClient.connect('connection string', function (err, mdb) {
db = mdb;
});
}
connect();
function insert(query, collection, fn) {
db.collection(collection)
.insert(query, function (er, da) {
fn(er, da);
});
}
function find(query, collection, fn) {
db.collection(collection)
.find(query).toArray(function (er, da) {
fn(er, da);
});
}
I don't want to use mongoose and prefer to learn and understand what's going on under the hood.
The examples available in documentation are not actually good for real life use cases. If you are using a server framework you can normally connect to mongo and share reference to the connection throughout application. I use hapi and connect to server via a plugin which allows me to store the handle to open connection. This allows you to clean up on shutdown of server. Their are many modules for managing mongo such as mongoose, waterline or wadofgum-mongodb which I have recently written.

node app: setup routes after mongoose db setup?

I'm currently developing a web app. I just started the development and i try to setup the routes after the db (mongoose Schemas and connection) is ready because i need the models in my router.js file. My Code looks like this right now:
File: server.js
//configuration here...
mongoose.connect( "mongodb://" + config.database.host + "/" + config.database.dbName );
var db = mongoose.connection;
db.on( "error", console.error.bind(console, "connection error:" ));
db.once( "open", function () {
var allModels = models.getAll( mongoose ); //retreive models from different files
router.setupRoutes(express, app, allModels); //setup all the routes also specified in other files
console.log("connected to database and created the routes!");
});
app.listen(port, host, function() {
console.log("");
console.log("Server started at: " + "http://" + host + ":" + port);
console.log("Press 'STRG+C' to stop the Server");
console.log("");
});
My Question is:
Is that the right way to do that? I call the app.listen function not inside this once("open") function (app.listen is at the bottom of this file and gets called before the routes are set up) My test routes are working but im not accesing the mongoose models right now. Should i call app.listen in the mongoose callback or like now at the end of my file?
i just want to make sure that this is the right way to do this. it seems to be the right way. mongoose said so... Look here
I wouldn't say that there's a right or a wrong way. It depends what you're trying to do. Here are my thoughts:
Do you want to have your server running if the database connection isn't working? Maybe because some routes don't involve the database? If that's what you're aiming for, you'd have to set up the routes outside the db connection callback. Something like this:
db.once('open', function() {
// set up routes that involve db connection
});
// set up routes that don't involve db connection
app.listen(port, host, function() {
});
If all of your routes involve database communication, I don't see a purpose to having app.listen outside of the db connection callback. Because the fact that the server is listening wouldn't be useful if the database connection is broken.
I would like to point to specific case. when we put the connection in the server.js The app will try to connect when it is lunched. And If error has been occured it will throw the error and never look back. However, when we put the connection in the routes, the app will try to reach the db only when it needs to, and every time it needs to.The thing that make us able to reach db related end points and none related end points and open to db status changements. So If the db has a problem and we fix it, no need to restart the server.

Resources