exported variables got undefined while functions get exported in node js - javascript

I am creating the nodejs application which uses the mongodb.
I am connecting to mongodb only once. I want to use db in all other api's so as to achieve the connection pooling.
I have following code for mongodb connectivity:
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var db;
var mongoUrl = "mongodb://localhost:27017/testDB";
/**
* Connects to the MongoDB Database with the provided URL
*/
exports.connect = function(callback){
if(!db){
MongoClient.connect(mongoUrl, function(err, _db){
if (err) { throw new Error('Could not connect: '+err); }
db = _db;
console.log(db);
connected = true;
console.log(connected +" is connected?");
callback(db);
});
}else{
console.log("Not connected tis time as I am already connected");
callback(db);
}
};
exports.db = db;
I am calling connect only once when server starts from app.js. Whenever other api such as signin, register get called, they should simply use db that is exported.
So my api calls will something like(please ignore the syntax error in api call :D):
var mongo = require('./mongo');
collection = mongo.db.collection("testCollection");
// Here mongo.db id undefined
collection.findOne({"name":"John"}, function(err, result){
// Do your stuff with result here
});
From other stackoverflow posts, I tried something like in mongo.js as
module.export{
db: db,
connect : function(callback){
//function code goes here
}
}
But still I am getting the undefined for mongo.db
How would I access mongo.db in my other files?
Thanks

The reason this happens is, because connect overwrites db in the module. The exports.db=db; is not executed after calling your connect function, but on execution of the module import.
So, when you call connect, db is set to another variable, but that is not exposed outside.
Didn't do much JS lately, but this should do it:
module.exports = new mongobj();
function mongobj() {
this.db = null;
this.connect = function(callback) { /* your connect code set mongobj.db */
this.db = /* new value */ ;
}
}
When you import the module, you get the object. Accessing the objects db property will always expose the latest db value set by the connect function of the module.
var mongo = require('yourmodule');
// mongo.db is null
mongo.connect(some callback);
// mongo.db is set

This connection add in main script file...
var mongodb = require('mongodb');
var mongodb = require('mongodb');
var MongoClient = require('mongodb').MongoClient;
var mongoUrl = "mongodb://localhost:27017/testDB";
ObjectId = module.exports = require("mongojs").ObjectId;
MongoClient.connect(mongoUrl, function(err, database){
if(err){
console.log("mongodb error >>"+err);
} else {
db = module.exports = database;
}});
db.collection('game_users').findOne({_id:ObjectId("123456789")},function(err, data) {});

define an object:
var db = {__db: undefined}
and then:
exports.db = db
const db = require('./mongo').db.__db

Related

Node js database connection in a separate module

I made node.js app that includes some REST services. Those services connect to a database (for example Oracle or DB2) to execute some query.
Since I'm a beginner in node.js programming, I have a question about my case:
What's the right way to access to a database? Is it better to have one connection reference while the app is running and use the same connection instance when REST services are called?
I found some examples that includes database connection in a separate module and use that module in app, something like that:
db2.js:
var db2 = require('ibm_db');
var db2ConnSettings = "DRIVER={DB2};DATABASE=mydb;HOSTNAME=localhost;UID=db2test;PWD=db2test;PORT=50000;PROTOCOL=TCPIP";
var db2Conn = db2.open(db2ConnSettings, function(err, conn) {
if (err)
return console.log(err);
});
module.exports = db2Conn;
server.js:
var express = require('express');
var app = express();
var db2Connection = require('./db2.js');
app.get('/data', function(req, res) {
console.log(db2Connection );
// make some query
});
When this service is called, db2connection is undefined. How come? How should I retrieve a db2 connection from db2.js file?
As said by #Sirko:
db2.js
var db2 = require('ibm_db');
var db2ConnSettings = "DRIVER={DB2};DATABASE=mydb;HOSTNAME=localhost;UID=db2test;PWD=db2test;PORT=50000;PROTOCOL=TCPIP";
var err, conn;
var callbacks = [];
module.exports = function(callback) {
// db2 module is called
if (err || conn) {
// connection has already been established
// (results of db2.open have been stored)
// callback immediately
callback(err, conn);
}
else {
// connection has not been established
// store the callback for when db connects
callbacks.push(callback);
}
};
db2.open(db2ConnSettings, function(_err, _conn){
// db has connected
err = _err; conn = _conn; // store results
var next_callback;
// array.pop() removed the last item from the array
// and returns it. if no items are left, returns null.
// so this loops through all stored callbacks.
while(next_callback = callbacks.pop()) {
// the removed item is stored in next_callback
next_callback(err, conn); // send connection results to callback
}
// no more items in callbacks to trigger
});
server.js
var express = require('express');
var app = express();
var db2Connection = require('./db2.js')(function(err, conn) {
// triggered if the connection has already been established
// or as soon as it HAS been established
app.get('/data', function(req, res) {
console.log(conn);
// ...
});
});
For Oracle with node-oracledb it's simple to create and use a connection pool. Your app would just get a free connection from the pool whenever it handles an HTTP REST request. Look at webapp.js and webapppromises.js in the examples. Node-oracledb has a 'connection pool queue' (see doc) which handles connection load spikes. It also has a 'connection pool cache' (also see the doc) which makes it easy to access a pool created in a different module.

Getting "globals is not defined" error when globals variable is clearly defined

I'm currently in the process of reorganizing the routes in my web application (I stupidly defined all the routes in index.js) and for some reason in several of these files I'm having this inexplicable problem: I'm getting errors saying the "globals" variable is undefined when it is, in fact, defined.
This is one of the offending files:
http://pastebin.com/7Q5ExZDa
At line 37 I log the contents of globals.DB_URL, and it exists. The very next line I get an error that globals isn't defined. What am I doing wrong?
mongodb://localhost:27017/[redacted_db_name] // console log output
--- Error: ReferenceError: globals is not defined ---
Location: function (err){
utilities.logError(err, arguments.callee.toString());
res.redirect("/");
return;
}
UPDATE:
First problem was solved: I wasn't importing globals.js in utilities.js, and was trying to call a function that needed data from globals to function.
Unfortunately, now I get this error:
--- Error: TypeError: Cannot call method 'connect' of undefined ---
Location: function (err){
utilities.logError(err, arguments.callee.toString());
res.redirect("/");
return;
}
This error happens at the second promise. I think it may have something to do with the code in utilities, specifically the identifyUserByToken function.
/**
* identifyUserByToken
* Compares a given session token against the session tokens collection
* executes a given callback function if a match is found
* #param {String} userToken The session token to search for
* #param {function(Object, String)} The callback function to be called upon success, failure, or error
*/
function identifyUserByToken(userToken, callback){
var user_tokens;
var users
var promise = new Promise(function(resolve, reject){
mongoClient.connect(globals.DB_URL)
.then(function(db){ // Search user_tokens for userToken
user_tokens = db.collection("user_tokens");
users = db.collection("users");
return user_tokens.find({token : userToken}).toArray();
})
.then(function(result){ // Search users for the returned userID
var userID = result[0].userid;
return users.find({ userid : userID }).toArray();
})
.then(function(matchingUsers){ // Pass returned user object to callback
var user = matchingUsers[0];
if(callback != undefined) callback(undefined, user);
resolve(user);
})
.catch(function(err){
if(callback != undefined) callback(err, undefined);
reject(err);
});
});
return promise;
}
I know this means mongodb is undefined, but I'm importing it in the file
var globals = require("./globals");
/* == Third Party Libraries == */
var chalk = require("chalk"); /* usage: console output coloring */
var crypto = require("crypto"); /* usage: cryptograpgic primitives (password hashing, etc...) */
var mongodb = require("mongodb"); /* usage: data storage schema */
var mongoClient = mongodb.mongoClient;
EDIT: Solved TypeError
Simple typo. In utilities I was assigning the mongoClient variable incorrectly
How it was being defined: var mongoClient = mongodb.mongoClient;
How it needed to be defined: var mongoClient = mongodb.MongoClient;
Sorry! My bad.
The issue is with  var mongoClient = mongodb.mongoClient; it should be with a capital M:
 var mongoClient = mongodb.MongoClient;

How to create New MongoDb Database using the Node JS driver

I want to create a new Database in MongoDB using the Node JS driver. I tried the following approaches, but none of them created any databases (I checked using the mongo shell and RoboMongo) and the worst part is, it is not showing any errors, below programs are executed successfully without any error (I mean, error is NULL)
First Method, using the Mongo Server
var Db = require('mongodb').Db,
Server = require('mongodb').Server;
var db = new Db('myNewDatabase', new Server('localhost', 27017));
db.open(function (err, db) {
if (err) {
console.dir('ERROR we are in the callback of the open ');
console.dir(err);
throw err;
}
// Use the admin database for the operation
var adminDb = db.admin();
console.dir('we are in the callback of the open');
db.close();
});
Second approach I followed is:
var server = "localhost";
var port = 27017;
var dbName = "myNewDatabase";
var mongodb = require('mongodb');
var mongoClient = mongodb.MongoClient;
var connString = "mongodb://"+server+":"+port+"/"+dbName;
mongoClient.connect(connString, function(err, db) {
console.dir(err);
if(!err) {
console.log("\nMongo DB connected\n");
db.collection('test_correctly_access_collections', function(err, col2) {
console.dir(err);
if(err) {
console.dir('Thier is a error in creating collection');
console.dir(err);
}
console.log("\nColllection created succesfully\n");
db.close();
});
}
else{
console.log("Mongo DB could not be connected");
process.exit(0);
}
});
According to this link, we can use getDatabase API to create a new database, i tried for the same API in the Node JS, but i am unable to find one.
As searched in google and stackOverflow for this question, but I am able to find, only very few. So i am posting the answer to this myself.
At first thank you #somallg , you are right i voted up your comment.
Answer is, you need to insert document into collection and then, MongoDB will create the New Database and also the collection. So, above approaches in my question can we re-written as follows to create a new database using the Node JS Driver:
First Appoarch
var Db = require('mongodb').Db,
Server = require('mongodb').Server;
var db = new Db('myNewDatabase', new Server('localhost', 27017));
db.open(function (err, db) {
if (err) {
console.dir('ERROR we are in the callback of the open ');
console.dir(err);
throw err;
}
var collection = db.collection("simple_document_insert_collection_no_safe");
collection.insert({hello:'world_no_safe'});
console.dir('we are in the callback of the open');
db.close();
});
second approach
var server = "localhost";
var port = 27017;
var dbName = "myNewDatabase";
var mongodb = require('mongodb');
var mongoClient = mongodb.MongoClient;
var connString = "mongodb://"+server+":"+port+"/"+dbName;
mongoClient.connect(connString, function(err, db) {
console.dir(err);
if(!err) {
var collection = db.collection("simple_document_insert_collection_no_safe");
collection.insert({hello:'world_no_safe'});
}
else{
console.log("Mongo DB could not be connected");
process.exit(0);
}
db.close();
});

How to return JSON from MongoDB in Node.js?

I have a mongodb database called pokemon with a collection called pokemons. Here is my attempt to write a function that will do a find() operation in mongodb:
'use strict';
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// db url
var url = 'mongodb://localhost:27017/pokemon';
exports.getPokemonByName = function (name) {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
var cursor = db.collection('pokemons').find({name: name});
// how to return json?
});
};
I then call this function in another file:
var express = require('express');
var router = express.Router();
router.get('/pokedex', function (req, res) {
res.jsonp(db.getPokemonByName('Dratini'));
})
This link is helpful in showing how to log mongodb data to the console by doing some sort of each() method on the cursor object, but I don't know how to return json through the getPokemonByName function. I tried to define an empty array on the root scope of the getPokemonByName function and push data into that array with each iteration of the .each method show in that link, but I think I still can't return that array because it happens after the fact.
BTW, I'm really just doing this for fun and to learn about MongoDB and Node.js, so I don't want to use or an ODM like Mongoose to do some of this work for me.
I was able to answer my question with help from node's native monogodb driver github page: See here.
In essence, what I did was to define my exported function within the MongoClient's connection function. For some reason I thought node exports had to be in the root of the module, but that's not the case. Here's a finished version:
'use strict';
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// db url
var url = 'mongodb://localhost:27017/pokemon';
var findDocuments = function(db, callback) {
// Get the documents collection
var collection = db.collection('pokemons');
// Find some documents
collection.find({name: 'Dratini'}).toArray(function(err, docs) {
assert.equal(err, null);
// assert.equal(2, docs.length);
console.log("Found the following records");
callback(docs);
});
}
// Use connect method to connect to the Server
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server");
findDocuments(db, function(docs) {
console.log(docs);
exports.getPokemonByName = function() {
return docs;
}
db.close();
});
});
And then in another file:
var express = require('express');
var router = express.Router();
router.get('/pokedex', function (req, res) {
res.jsonp(db.getPokemonByName());
});
Of course, this solution requires that I hardcode queries, but I'm okay with that for now. Will cross that bridge when I come to it.
Found a simple tweak for this. Let say the callback to the findOne returns result then you can convert the result to JSON object like this
result = JSON.parse(JSON.stringify(result))
Now you can access the result and its fields simply with the dot operator.
this may help
var cursor = db.collection('pokemons').find({name:name}).toArray(function(err,arr){
return arr;
});
You can use callbacks on find function to return the json.
Try
exports.getPokemonByName = function (name,callback) {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
var cursor = db.collection('pokemons').find({name: name},function(err,result){
if(err)
{
callback(err,null);
}
if(result)
callback(null,result);
});
});
};
router.get('/pokedex', function (req, res) {
db.getPokemonByName('Dratini',function(err,result){
if(result)
{
res.jsonp(result);
}
});
})

How to create a user model with node.js?

I'd like to create a model to handle everything related to users, starting with a findOne() function.
app.js:
var u = new User(client);
u.findOne(function(error, user) {
console.log(error, user);
});
models/User.js:
var User = function (client) {
this.client = client
};
User.prototype.findOne = function (id, callback) {
client.connect();
client.get('testkey', function(error, result) {
var test = "hello#world.com";
callback(null, test);
client.close();
});
};
module.exports = User;
node.js complains findOne() would be undefined.
What's the correct way of creating such models and providing them with objects, like database pools etc.?
Your code contains various errors:
You do not use new when creating the instance
You mixed a function with the object literal syntax:
var User = function (client) {
client: client
};
You want this.client = client; instead. Right now the function body does nothing as it just defines a label called client does nothing with the variable client.
I would suggest you to search for an existing ORM for node.js instead of trying to write one on your own.

Categories