Can Not Retrieve Nodejs MySQl Data From Database via sub function call - javascript

I have two files named login.js and dbMySql.js.
login.js is the main file that will run dbMySql.js, which is a submodule for the DB connection.
I can run getQuery() from dbMySql.js by using object.method call.
getQuery() also works fine and retrieves data from the database.
How can I get this data to my Main module from the database module? How can I return res variable to main function in login.js module
Code For login.js:
var MySqlConnect = require('./dbMySql');
var app = express();
var dbConnect = MySqlConnect("localhost", "root", "root", "mydb");
dbConnect.getQuery("select * from `test`");
console.log(dbConnect.resD);
Code For dbMySql.js:
function MySqlConnect(dbhost, dbuser, dbpassword, dbname) {
var MySqlConnect = require('mysql');
var con;
this.dbhost = dbhost;
this.dbuser = dbuser;
this.dbpassword = dbpassword;
this.dbname = dbname;
this.resultData = 'Def';
con = MySqlConnect.createConnection({
host: dbhost,
user: dbuser,
password: dbpassword,
database: dbname
})
con.connect(function (err) {
if (err) throw err;
})
function getQuery(query1) {
con.query(query1, function (err, res) {
if (err) throw err;
})
return {
resD: res
};
}
return {
getQuery: getQuery,
};
};
module.exports = MySqlConnect;
I want Retrieved Data in Main module via return method or any that will run successfully.

Vary Simple Answer I have found by run and execute after efforts.
just pass res form db to callback function parameter and run this fucntion from main module

Related

NodeJS and MongoDB losing the definition of a variable even with module.exports

Hello i'm trying to fetch some partner names from my mongodb database and put them into a list of variables. But it for some reason loses it's definition when I try to export it. What's going on?
This is the first file.
///// mongodb.js /////
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const findDocuments = function(db, callback) {
// Get the documents collection
const collection = db.collection('partners');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
callback(docs);
});
};
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'yarle';
// Use connect method to connect to the server
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
console.log("Connected succesfully to Database");
const db = client.db(dbName);
findDocuments(db, function(docs) {
module.exports = {
partner1: console.log(docs[0]['partner_name']),
partner2: console.log(docs[1]['partner_name']),
partner3: console.log(docs[2]['partner_name']),
};
client.close();
});
});
//console.log(Object.keys(partners[0][0]));
And this is the end file.
///// Endfile.ts /////
import { Request, Response } from 'express';
import { PartnersList } from './data.d';
var partners = require( './mongodb.js');
console.log(partners.partner1);
const titles = [
partners.partner1,
partners.partner2,
partners.partner3,
];
Your problem is not with module.exports, it's with asynchronous programming. When you call MongoClient.Connect, the code in your callback does not get executed synchronously. It gets executed some time in the future. You have no control over when that happens.
The same thing is true of the findDocument callback.
Programming asynchronously is a little trickier, but you will have to learn it to write modern javascript. Asynchrony is a central tenet of nodejs. Read on it, learn examples, and your problem will become clear.
Instead of exporting the values of partner1, 2 and 3, export a function with a callback. This new function can call MongoClient.Connect, passing down the callback. Endfile.ts can now call your newly created asynchronous function and assign the titles array in the callback.
Like this:
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const findDocuments = function (db, callback) {
// Get the documents collection
const collection = db.collection('partners');
// Find some documents
collection.find({}).toArray(function (err, docs) {
assert.equal(err, null);
callback(docs);
});
};
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'yarle';
module.exports.getPartners = (callback) {
// Use connect method to connect to the server
MongoClient.connect(url, function (err, client) {
if (err) {
callback(err);
return;
}
console.log("Connected succesfully to Database");
const db = client.db(dbName);
findDocuments(db, function (docs) {
const partners = {
partner1: docs[0]['partner_name'],
partner2: docs[1]['partner_name'],
partner3: docs[2]['partner_name']
};
callback(null, partners);
client.close();
});
});
}
and this
import { Request, Response } from 'express';
import { PartnersList } from './data.d';
var mongoClient = require('./mongodb.js');
mongoClient.getPartners(function (err, partners) {
assert.equal(null, err);
const titles = partners;
});

mongodb: cannot define variable [duplicate]

I'm using the node-mongodb-native driver with MongoDB to write a website.
I have some questions about how to manage connections:
Is it enough using only one MongoDB connection for all requests? Are there any performance issues? If not, can I setup a global connection to use in the whole application?
If not, is it good if I open a new connection when request arrives, and close it when handled the request? Is it expensive to open and close a connection?
Should I use a global connection pool? I hear the driver has a native connection pool. Is it a good choice?
If I use a connection pool, how many connections should be used?
Are there other things I should notice?
The primary committer to node-mongodb-native says:
You open do MongoClient.connect once when your app boots up and reuse
the db object. It's not a singleton connection pool each .connect
creates a new connection pool.
So, to answer your question directly, reuse the db object that results from MongoClient.connect(). This gives you pooling, and will provide a noticeable speed increase as compared with opening/closing connections on each db action.
Open a new connection when the Node.js application starts, and reuse the existing db connection object:
/server.js
import express from 'express';
import Promise from 'bluebird';
import logger from 'winston';
import { MongoClient } from 'mongodb';
import config from './config';
import usersRestApi from './api/users';
const app = express();
app.use('/api/users', usersRestApi);
app.get('/', (req, res) => {
res.send('Hello World');
});
// Create a MongoDB connection pool and start the application
// after the database connection is ready
MongoClient.connect(config.database.url, { promiseLibrary: Promise }, (err, db) => {
if (err) {
logger.warn(`Failed to connect to the database. ${err.stack}`);
}
app.locals.db = db;
app.listen(config.port, () => {
logger.info(`Node.js app is listening at http://localhost:${config.port}`);
});
});
/api/users.js
import { Router } from 'express';
import { ObjectID } from 'mongodb';
const router = new Router();
router.get('/:id', async (req, res, next) => {
try {
const db = req.app.locals.db;
const id = new ObjectID(req.params.id);
const user = await db.collection('user').findOne({ _id: id }, {
email: 1,
firstName: 1,
lastName: 1
});
if (user) {
user.id = req.params.id;
res.send(user);
} else {
res.sendStatus(404);
}
} catch (err) {
next(err);
}
});
export default router;
Source: How to Open Database Connections in a Node.js/Express App
Here is some code that will manage your MongoDB connections.
var MongoClient = require('mongodb').MongoClient;
var url = require("../config.json")["MongoDBURL"]
var option = {
db:{
numberOfRetries : 5
},
server: {
auto_reconnect: true,
poolSize : 40,
socketOptions: {
connectTimeoutMS: 500
}
},
replSet: {},
mongos: {}
};
function MongoPool(){}
var p_db;
function initPool(cb){
MongoClient.connect(url, option, function(err, db) {
if (err) throw err;
p_db = db;
if(cb && typeof(cb) == 'function')
cb(p_db);
});
return MongoPool;
}
MongoPool.initPool = initPool;
function getInstance(cb){
if(!p_db){
initPool(cb)
}
else{
if(cb && typeof(cb) == 'function')
cb(p_db);
}
}
MongoPool.getInstance = getInstance;
module.exports = MongoPool;
When you start the server, call initPool
require("mongo-pool").initPool();
Then in any other module you can do the following:
var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
// Query your MongoDB database.
});
This is based on MongoDB documentation. Take a look at it.
Manage mongo connection pools in a single self contained module. This approach provides two benefits. Firstly it keeps your code modular and easier to test. Secondly your not forced to mix your database connection up in your request object which is NOT the place for a database connection object. (Given the nature of JavaScript I would consider it highly dangerous to mix in anything to an object constructed by library code). So with that you only need to Consider a module that exports two methods. connect = () => Promise and get = () => dbConnectionObject.
With such a module you can firstly connect to the database
// runs in boot.js or what ever file your application starts with
const db = require('./myAwesomeDbModule');
db.connect()
.then(() => console.log('database connected'))
.then(() => bootMyApplication())
.catch((e) => {
console.error(e);
// Always hard exit on a database connection error
process.exit(1);
});
When in flight your app can simply call get() when it needs a DB connection.
const db = require('./myAwesomeDbModule');
db.get().find(...)... // I have excluded code here to keep the example simple
If you set up your db module in the same way as the following not only will you have a way to ensure that your application will not boot unless you have a database connection you also have a global way of accessing your database connection pool that will error if you have not got a connection.
// myAwesomeDbModule.js
let connection = null;
module.exports.connect = () => new Promise((resolve, reject) => {
MongoClient.connect(url, option, function(err, db) {
if (err) { reject(err); return; };
resolve(db);
connection = db;
});
});
module.exports.get = () => {
if(!connection) {
throw new Error('Call connect first!');
}
return connection;
}
If you have Express.js, you can use express-mongo-db for caching and sharing the MongoDB connection between requests without a pool (since the accepted answer says it is the right way to share the connection).
If not - you can look at its source code and use it in another framework.
You should create a connection as service then reuse it when need.
// db.service.js
import { MongoClient } from "mongodb";
import database from "../config/database";
const dbService = {
db: undefined,
connect: callback => {
MongoClient.connect(database.uri, function(err, data) {
if (err) {
MongoClient.close();
callback(err);
}
dbService.db = data;
console.log("Connected to database");
callback(null);
});
}
};
export default dbService;
my App.js sample
// App Start
dbService.connect(err => {
if (err) {
console.log("Error: ", err);
process.exit(1);
}
server.listen(config.port, () => {
console.log(`Api runnning at ${config.port}`);
});
});
and use it wherever you want with
import dbService from "db.service.js"
const db = dbService.db
I have been using generic-pool with redis connections in my app - I highly recommend it. Its generic and I definitely know it works with mysql so I don't think you'll have any problems with it and mongo
https://github.com/coopernurse/node-pool
I have implemented below code in my project to implement connection pooling in my code so it will create a minimum connection in my project and reuse available connection
/* Mongo.js*/
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/yourdatabasename";
var assert = require('assert');
var connection=[];
// Create the database connection
establishConnection = function(callback){
MongoClient.connect(url, { poolSize: 10 },function(err, db) {
assert.equal(null, err);
connection = db
if(typeof callback === 'function' && callback())
callback(connection)
}
)
}
function getconnection(){
return connection
}
module.exports = {
establishConnection:establishConnection,
getconnection:getconnection
}
/*app.js*/
// establish one connection with all other routes will use.
var db = require('./routes/mongo')
db.establishConnection();
//you can also call with callback if you wanna create any collection at starting
/*
db.establishConnection(function(conn){
conn.createCollection("collectionName", function(err, res) {
if (err) throw err;
console.log("Collection created!");
});
};
*/
// anyother route.js
var db = require('./mongo')
router.get('/', function(req, res, next) {
var connection = db.getconnection()
res.send("Hello");
});
If using express there is another more straightforward method, which is to utilise Express's built in feature to share data between routes and modules within your app. There is an object called app.locals. We can attach properties to it and access it from inside our routes. To use it, 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, or indeed any other data you wish to share around the modules of you app can now be accessed within your routes with req.app.locals 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 creation of any additional modules.
Best approach to implement connection pooling is you should create one global array variable which hold db name with connection object returned by MongoClient and then reuse that connection whenever you need to contact Database.
In your Server.js define var global.dbconnections = [];
Create a Service naming connectionService.js. It will have 2 methods getConnection and createConnection.
So when user will call getConnection(), it will find detail in global connection variable and return connection details if already exists else it will call createConnection() and return connection Details.
Call this service using <db_name> and it will return connection object if it already have else it will create new connection and return it to you.
Hope it helps :)
Here is the connectionService.js code:
var mongo = require('mongoskin');
var mongodb = require('mongodb');
var Q = require('q');
var service = {};
service.getConnection = getConnection ;
module.exports = service;
function getConnection(appDB){
var deferred = Q.defer();
var connectionDetails=global.dbconnections.find(item=>item.appDB==appDB)
if(connectionDetails){deferred.resolve(connectionDetails.connection);
}else{createConnection(appDB).then(function(connectionDetails){
deferred.resolve(connectionDetails);})
}
return deferred.promise;
}
function createConnection(appDB){
var deferred = Q.defer();
mongodb.MongoClient.connect(connectionServer + appDB, (err,database)=>
{
if(err) deferred.reject(err.name + ': ' + err.message);
global.dbconnections.push({appDB: appDB, connection: database});
deferred.resolve(database);
})
return deferred.promise;
}
In case anyone wants something that works in 2021 with Typescript, here's what I'm using:
import { MongoClient, Collection } from "mongodb";
const FILE_DB_HOST = process.env.FILE_DB_HOST as string;
const FILE_DB_DATABASE = process.env.FILE_DB_DATABASE as string;
const FILES_COLLECTION = process.env.FILES_COLLECTION as string;
if (!FILE_DB_HOST || !FILE_DB_DATABASE || !FILES_COLLECTION) {
throw "Missing FILE_DB_HOST, FILE_DB_DATABASE, or FILES_COLLECTION environment variables.";
}
const client = new MongoClient(FILE_DB_HOST, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
class Mongoose {
static FilesCollection: Collection;
static async init() {
const connection = await client.connect();
const FileDB = connection.db(FILE_DB_DATABASE);
Mongoose.FilesCollection = FileDB.collection(FILES_COLLECTION);
}
}
Mongoose.init();
export default Mongoose;
I believe if a request occurs too soon (before Mongo.init() has time to finish), an error will be thrown, since Mongoose.FilesCollection will be undefined.
import { Request, Response, NextFunction } from "express";
import Mongoose from "../../mongoose";
export default async function GetFile(req: Request, res: Response, next: NextFunction) {
const files = Mongoose.FilesCollection;
const file = await files.findOne({ fileName: "hello" });
res.send(file);
}
For example, if you call files.findOne({ ... }) and Mongoose.FilesCollection is undefined, then you will get an error.
npm i express mongoose
mongodb.js
const express = require('express');
const mongoose =require('mongoose')
const app = express();
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://localhost:27017/db_name', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('MongoDB Connected...'))
.catch((err) => console.log(err))
app.listen(3000,()=>{ console.log("Started on port 3000 !!!") })
node mongodb.js
Using below method you can easily manage as many as possible connection
var mongoose = require('mongoose');
//Set up default mongoose connection
const bankDB = ()=>{
return mongoose.createConnection('mongodb+srv://<username>:<passwprd>#mydemo.jk4nr.mongodb.net/<database>?retryWrites=true&w=majority',options);
}
bankDB().then(()=>console.log('Connected to mongoDB-Atlas bankApp...'))
.catch((err)=>console.error('Could not connected to mongoDB',err));
//Set up second mongoose connection
const myDB = ()=>{
return mongoose.createConnection('mongodb+srv://<username>:<password>#mydemo.jk4nr.mongodb.net/<database>?retryWrites=true&w=majority',options);
}
myDB().then(()=>console.log('Connected to mongoDB-Atlas connection 2...'))
.catch((err)=>console.error('Could not connected to mongoDB',err));
module.exports = { bankDB(), myDB() };

require function and variable from another file = nodejs

I am trying to offload some of the bulk from my app and came across this issue.
Here is my code:
// foo.js:
var mysql = require('mysql');
module.exports = {
home: function () {
return mysql.createConnection({
host : '2.2.2.2',
user: 'admin',
password: 'xxxxxx',
database : 'mlb'
});
}
// bar.js:
var dbConnect = require('./foo.js');
dbConnect.home.query('SELECT * from batters;', function(err, res, body) {
if (err) throw err;
var string_data = JSON.stringify(res);
var jsonData = JSON.parse(string_data);
console.log(jsonData);
});
The error i receive is undefined is not a function... What am I doing wrong?
Wouldn't home need to be like this:
dbConnect.home().query
I needed to instantiate the imported function before calling its method.
Correct code for bar.js is:
var dbConnect = require('./test.js');
var connection = dbConnect.home();
connection.query('SELECT * from batters;', function(err, res, body) {
if (err) throw err;
var string_data = JSON.stringify(res);
var jsonData = JSON.parse(string_data);
console.log(jsonData);
});

Grunt task not calling external javascript task

I am trying to insert data to mongodb using a grunt task. Init.js is the file which is located in "tasks" directory. So, i registered the task as:
grunt.registerTask('dbinit', function () {
grunt.task.loadTasks('tasks');
}
tasks directory has Init.js:
var mongoose = require('mongoose'),
config = require('/lib/config/config.js'),
mongoose = require('mongoose'),
dbmodel = require('/lib/models/user.js'),
db;
mongoose.connect(config.mongo.uri, config.mongo.options);
db = mongoose.connection;
db.on('open', function () {
var user = new dbmodel.User({
userId : 'bond007'
});
console.log('Adding seed user: '+user);
newUser.save(function (err, product, numberAffected) {
if (err) {
console.log(err);
} else {
console.log("saved user: "+user.userId);
}
db.close();
});
});
The problem is that Init.js is never called. I am not sure if it is an async issue or issue with calling Init.js but I see the "dbinit" task "Done without errors".
Grunt tasks by default execute synchronously, the task will finish and not wait for the mongoose connection to open. Use this.async() within the task to have the task wait.
A better strategy might be to wrap parts within tasks/Init.js in a task like such:
var mongoose = require('mongoose'),
config = require('/lib/config/config.js'),
mongoose = require('mongoose'),
dbmodel = require('/lib/models/user.js'),
db;
grunt.registerTask('dbinit', function() {
var done = this.async();
mongoose.connect(config.mongo.uri, config.mongo.options);
db = mongoose.connection;
db.on('open', function () {
var user = new dbmodel.User({
userId : 'bond007'
});
console.log('Adding seed user: '+user);
newUser.save(function (err, product, numberAffected) {
if (err) {
console.log(err);
} else {
console.log("saved user: "+user.userId);
}
db.close();
done(); // Call done to close the task
});
});
});
Then just use grunt.loadTasks('tasks'); in your gruntfile.

Node.js: how to load modules without executing them?

I have a simple file model.js like follows:
var mongo = require('mongodb');
var mongoUri = process.env.MONGOLAB_URI ||
process.env.MONGOHQ_URL ||
'mongodb://localhost/mydb';
exports.connect = mongo.Db.connect(mongoUri, function(err, db) {
console.log("Connect to the database successfully")
});
and in my web.js I load the model using model = require('./model.js'). One werid thing is that although I did not call model.connect(), the message "Connect to the database successfully" still got logged to my console. Why is this happening and is there a way to avoid it?
EDIT:Never mind I have found a workaround:
exports.connect = function(){
mongo.Db.connect(mongoUri, function(err, db) {
console.log("Connect to the database successfully")
});
}
exports.connect = mongo.Db.connect(mongoUri, function(err, db) {
console.log("Connect to the database successfully")
});
You just called mongo.Db.connect() and assigned its result to exports.connect.
That code runs as soon as you require() the module.
Instead, you need to create a function:
exports.connect = function() { ... };

Categories

Resources