Accessing a module from all external JS files in Node.js - node.js

Context
If I have say 2 classes e.g. User.js class and Log.js class which both access a database in their own unique methods, and I have installed a MySQL database module e.g. db-mysql.
Question
How can I make it so the same (one) database instance can be used across both JS files?
Thoughts
The two methods I can think of at the moment are not very memory conscious I guess:
pass db parameter in
function(db){
this.db = db;
}
create an instance of it inside every class
function(){
this.db = require(moduleName);
}
I’m just looking for the best way and need a bit of guidance.

Create a separate file where you connect to db. You keep that connection in that modules' closure, and when you later require that module, from any other file, it will use that same connection.
The simple example is something like this: lib/db.js
var mysql = require('db-mysql');
var settings = { // import these from ENV is a good pattern
hostname: 'localhost'
, user: 'user'
, pw: '****'
, database: 'base'
}
var db =new mysql.Database(settings).on('error', function(error) {
console.log('ERROR: ' + error);
}).on('ready', function(server) {
console.log('Connected to ' + server.hostname + ' (' + server.version + ')');
}).connect();
module.exports = db;
Then use this in other files:
var db = require('../lib/db');
db.query(...)
You can even abstract some basic queries in the db.js, something like:
function getUsers(filterString, callback) {
db.query().select('id, username, email').from('users').where('username like', filterString)
.execute(callback);
}
module.exports.getUsers = getUsers
Then in other files:
var db = require('lib/db');
db.getUsers('mike', function(err, rows, cols) {
if(err) throw err;
return [rows, cols];
});

Pass the DB Parameter in.
Also create a new JS file called DBConfig.js where you can store the credentials for the MySQL DB. Use this javascript object to initiate your db. For Ex:
var db = require('DBConfig);
Inside your DBConfig.js, you can write
module.exports = {
host:'<host_url>',
username: root,
password: '',
database: '<database-name>'
}
In this manner you can use the same config accross the JS files.

Related

Mysql-Node pool - release connection error and Singleton in Node

configuration.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'localhost',
user : 'root',
password : '',
database : 'test'
});
pool.getConnection( function(err, connection) {
if (err) console.error('error connecting: ' + err.stack);
return;
});
module.exports = pool;
user.js model file
var async = require("async");
var homePage = function HomePage( user_id ) {
this.user_id = user_id;
this.db = require('../config/configuration');
}
homePage.prototype.getCourse = function( callback ){
var self = this;
self.db.query(' my sql query ', [ self.user_id ], function (error, results, fields) {
self.db.release();
callback(err,results);
});
};
I have exported my db connection here and I require that module(configuration.js) in every model file. I assume that it will load the same db connection everytime as from the Node.js docs:
every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.
As this is the first time I am coding in JS and asynchronous programming I am confused about few things. Will my same configuration file be loaded as I want to have a singleton kinda pattern for my db file. Is my approach correct ?
When I do - self.db.release() I assume I am releasing a connection back to the pool. But it's giving an error and I am unable to figure it out as everything else is working fine.The error is -
self.db.release() is not a function
If I comment this line it's working fine. Is there a way to see what this release is returning as it will help in debugging.
Moreover is my approach correct.

Node.js, Express and Postgres design

I am creating an API with Node.js and Express. I'm using Postgres as DB.
I would like to create a "global object", called DBConn or something, that I can access from everywhere in the App. This object would have the functions for inserting, updating, validating, etc.
How would be the general architecture in Node and Express for this to work? Does it make sense in Node to instantiate it just once and keep the communication with the DB open, or should I instantiate it everytime I want to perform a DB action?
Here's everything that you are looking for, using pg-promise:
// Users repository:
var repUsers = function (obj) {
return {
add: function (name) {
return obj.none("insert into users(name) values($1)", name);
},
delete: function (id) {
return obj.none("delete from users where id=$1", id);
}
// etc...
};
};
var options = {
extend: function () {
// extending the protocol:
this.users = repUsers(this);
}
};
var pgp = require('pg-promise')(options);
var cn = "postgres://username:password#host:port/database";
var db = pgp(cn); // your global database instance;
db.users.add("John")
.then(function () {
// success;
})
.catch(function (error) {
// error;
});
This will also manage your database connection automatically, you will just keep using variable db throughout your application.
And setting up a repository is optional, you can always use in-line queries instead. See the library for details and more examples.
I don't know Postgres at all,but maybe you can try this:
Create a file named 'DBConn.js' in YourApp/common directory.
DBConn.js:
var DBConn = exports = modules.exports = {}
//code to connect to database
....
//insert update detele select
DBConn.insert = function(arguments) {
//some code
}
.....
DBConn.update = function(arguments) {
//some code
}
Then you can require it in any other controller like YouApp/controller/UserController.js
UserController.js:
var DBConn = require('../common/DBConn.js')
Example of module cache
index.js:
require('./DB.js');
require('./DB.js');
DB.js
var DB = exports = module.exports = {}
function connect() {
//connect to database code
console.log('Connect!');
}
connect();
//other code
Then node index.js,we can see that 'Connect!' only logged once.
Because when we first require('DB.js'),node.js put it to the module cache,and when we require DB.js again,we get DB.js from cache.

MongoClient multiple connections using Node.js

I want to create a module for NodeJS to connecto to MongoDB. I've seen that the new, better approach is to use MongoClient, but I can't get to know how can I make concurrent operations on the database. The goal I want to achieve is to have functions to abstract the database, like the following:
exports.insertItem(item){
//Whatever
}
According to the docs, I am supposed to connect to the database this way:
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, db) {
//Do stuff on the db object
});
The problem is how I am supposed to reuse the db object if it's not in a scope I can use to export functions in node? Am I supposed to make a MongoClient.connect() on every function that deals with the DB?
You make a single db connection and reuse it everywhere
A typical pattern for modules is
export.myinsert = function(db) {
return function(whatever) {
}
}
and then do
require('mymodule')(db)
Have a look at an example
https://github.com/christkv/tic-tac-toe-steps
Here is a stripped down version of some code that I use to show the overall concept...Hopefully this helps you get started.
var mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient;
var db;
// Initialize our connection to MongoDB once
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, database){
if(err){
console.log('MongoClient connect failed');
console.log(err);
}
db = database;
});
exports.Connect = function (callback) {
callback(db);
};
exports.MongoClient = MongoClient;
exports.ObjectID = mongodb.ObjectID;
To use it
var Connect = require('myMongo').Connect;
Connect(function(db){
// then use your db.collection() stuff here
})

DB Connection in mongo-db native client

I have an express/nodeJs app which will use mongo-db native client for persistance in Mongo-db. Now my problem is that most of the example I have seen have one collection and therefore do the connection in that js file, like this tutorial(which is mentioned in mongo-db native client docs). There the connection code is like this:
var Db = require('mongodb').Db;
var Connection = require('mongodb').Connection;
var Server = require('mongodb').Server;
var BSON = require('mongodb').BSON;
var ObjectID = require('mongodb').ObjectID;
ArticleProvider = function(host, port) {
this.db= new Db('node-mongo-blog', new Server(host, port, {auto_reconnect: true}, {}));
this.db.open(function(){});
};
ArticleProvider.prototype.getCollection= function(callback) {
this.db.collection('articles', function(error, article_collection) {
if( error ) callback(error);
else callback(null, article_collection);
});
};
ArticleProvider.prototype.findAll = function(callback) {
this.getCollection(function(error, article_collection) {
if( error ) callback(error)
else {
article_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
There are other methods also which I kept out to keep it small(check in the above url for full tutorial).
My problem is that I have few more collections and therefore I am worried as to how to make a single connection to the database and use it for all the collections. I would also like if you can specify how to make connections to replica-sets also for reads and the main database for writes.
Or should I make calls to connections in each of my collection.js files like the above mentioned tutorial has done in one.
Please help me.
Try using the singleton pattern:
In your main express app.js connect to the database and create the database instance:
var Database = require('database.js');
...
mongodb.connect(config.dbAddress, function (err, db) {
if(err) {
return console.log('Error connection to DB');
}
Database.setDB(db);
app.listen(config.appPort);
});
Then in any other file you need to use the database require database.js again:
var Database = require('database.js');
...
ArticleProvider = function() {
this.db = Database.getDB();
};
...
Finally the database.js file follows the singleton pattern:
/**
Database Singleton Object
database.js is used throughout the app to access the db object. Using mongodb
native drivers the db object contains a pool of connections that are used to
make requests to the db. To use this singleton object simply require it and
either call getDB() or setDB(). The idea is to use setDB in app.js just
after we connect to the db and receive the db object, then in any other file we
need the db require and call getDB
**/
var mongodb = require('mongodb');
var singleton = (function() {
var instance; //Singleton Instance
function init() {
var _db; //Instance db object (private)
//Other private variables and function can be declared here
return {
//Gets the instance's db object
getDB: function() {
return _db;
},
//Sets the instance's db object
setDB: function(db) {
_db = db;
}
//Other public variables and methods can be declared here
};
}
return {
//getInstance returns the singleton instance or creates a new one if
//not present
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
module.exports = singleton.getInstance();

How to properly pass mysql connection to routes with express.js

I am trying to figure out the best way to pass a mysql connection (using node-mysql) between my routes for express.js. I am dynamically adding each route (using a for each file loop in routes), meaning I can't just pass in the connection to routes that need it. I either need to pass it to every route or none at all. I didn't like the idea of passing it to ones that dont need it so I created a dbConnection.js that the routes can individually import if they need. The problem is that I dont think I am doing it correctly. As of now, my dbConnection.js contains:
var mysql = require('mysql');
var db = null;
module.exports = function () {
if(!db) {
db = mysql.createConnection({
socketPath: '/tmp/mysql.sock',
user: '*********',
password: '*********',
database: '**********'
});
}
return db;
};
And I am importing it into each route using:
var db = require('../dbConnection.js');
var connection = new db();
But I would like to do it like this:
var connection = require('../dbConnection.js');
When I try it like this, however, I get an error saying connection has no method 'query' when I try to make a query.
I find it more reliable to use node-mysql's pool object. Here's how I set mine up. I use environment variable for database information. Keeps it out of the repo.
database.js
var mysql = require('mysql');
var pool = mysql.createPool({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASS,
database: process.env.MYSQL_DB,
connectionLimit: 10,
supportBigNumbers: true
});
// Get records from a city
exports.getRecords = function(city, callback) {
var sql = "SELECT name FROM users WHERE city=?";
// get a connection from the pool
pool.getConnection(function(err, connection) {
if(err) { console.log(err); callback(true); return; }
// make the query
connection.query(sql, [city], function(err, results) {
connection.release();
if(err) { console.log(err); callback(true); return; }
callback(false, results);
});
});
};
Route
var db = require('../database');
exports.GET = function(req, res) {
db.getRecords("San Francisco", function(err, results) {
if(err) { res.send(500,"Server Error"); return;
// Respond with results as JSON
res.send(results);
});
};
your solution will work if use db() instead of new db(), which returns an object and not the db connection
var db = require('../dbConnection.js');
//var connection = new db();
var connection = db();

Resources