error connecting to mongodb on Nodejs - node.js

I am trying to connect to mongodb from node and I am getting below error
node_modules\mongodb\lib\mongo_client.js:458
throw err
^
ReferenceError: connect is not defined
I am using the mongodb module version
2.0.48
I am trying to run a simple test code
(function (dbase) {
var mdb = require('mongodb');
var mongoUrl = "mongodb://localhost:27017/theBoard";
var connection;
dbase.dbConnection = function (next) {
if (connection) {
next(null, connection);
} else {
mdb.MongoClient.connect(mongoUrl, function(err, db) {
if (err) {
next(err, null);
} else {
console.log("connected");
connection = { db: db , notes: db.collection("notes")};
next(null, connection);
}
});
}
}
Can someone please help me understand this issue.
---Additional information
data module -
(function (data) {
var mdb = require('./db.js');
data.GetCategory = function() {
mdb.dbConnection(function(err, db) {
if (err)
console.log("Error connecting to mango");
if (connect) {
db.notes.count(function(err, count) {
if (err)
console.log("Failed to retreive collection");
else
console.log("Count - "+count);
});
console.log("Connected");
}
});
}})(module.exports);
db.js
(function (dbase) {
var mdb = require('mongodb');
var mongoUrl = "mongodb://localhost:27017/theBoard";
var connection;
dbase.dbConnection = function (next) {
if (connection) {
next(null, connection);
} else {
mdb.MongoClient.connect(mongoUrl, function(err, db) {
if (err) {
next(err, null);
} else {
console.log("connected");
connection = { db: db , notes: db.collection("notes") };
next(null, connection);
}
});
}
} })(module.exports);
Controller -
(function (controller) {
var data = require('.././data');
controller.init = function (app) {
app.get("/", handleRequest);
}
var handleRequest = function (req, res) {
data.GetCategory();
var a = {};
a.send = "Mamma is coming home";
res.send(a);
}
})(module.exports);

Just in case some one runs into an issue like this due to bad coding practice even if it for test purpose is to never have function names which are the same as the function names in the API. In db.js I had an undefined variable named connect which trowing and error when it was accessed and since it was called through the API function called "connect" the error was thrown by the API leading me to believe that the API function had an issue

Related

MongoDB-Express: Cannot get the client/db out of connect function

I am separating the connect function of MongoDB to a separate module, so that the mongoDB connection is reusable. The issue is, I could not get the client/DB variable outside the connect function. It shows undefined.
var MongoClient = require('mongodb').MongoClient;
var _client;
var mongoURL = "mongodb://localhost:27017/";
module.exports = {
connectToMongoServer: (callback) => {
MongoClient.connect(mongoURL,{ useNewUrlParser: true },function(err,client){
_client = client;
return callback(err);
});
},
getClient: () => {
return _client;
}
};
Within the connect function, the _client details contains the information, but if I return it using getClient, it shows undefined.
MongoDB - v3.6.5
Node - v9.9.0
I've made up a snippet which should work the same ad your code, and it works.
So I think the problem is how you are calling your function getClient(); are you sure you are calling it after it get connected?
var _client;
function someAsyncFunc(callback) {
setTimeout(() => callback(false, 'client'), 500);
}
const file = {
connectToMongoServer: (callback) => {
someAsyncFunc(function(err, client) {
_client = client;
return callback(err);
});
},
getClient: () => {
return _client;
}
};
console.log('display one :', file.getClient());
file.connectToMongoServer((err) => {
console.log('display error :', err);
console.log('display two :', file.getClient());
});

Check if mongoDB is connected

I have mongoDB in my app.
I want to check if mongoDB is connected, before I listen to the app.
Is it the best way for doing it?
This is my server.js file:
var express = require('express');
var mongoDb = require('./mongoDb');
var app = express();
init();
function init() {
if (mongoDb.isConnected()) {
app.listen(8080, '127.0.0.1');
}
else {
console.log('error');
}
}
isConnected runs getDbObject.
getDbObject connects to mongoDB and returns an object:
connected (true/false), db (dbObject or error).
Then, isConnected resolve/reject by connected property.
This is mongoDb.js file:
//lets require/import the mongodb native drivers.
var mongodb = require('mongodb');
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/myDb';
var connectingDb; // promise
//We need to work with "MongoClient" interface in order to connect to a mongodb server.
var MongoClient = mongodb.MongoClient;
init();
module.exports = {
isConnected: isConnected
}
// Use connect method to connect to the Server
function init() {
connectingDb = new Promise(
function (resolve, reject) {
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
reject(err);
}
else {
console.log('Connection established to', url);
//Close connection
//db.close();
resolve(db);
}
});
}
);
}
function getDbObject() {
return connectingDb().then(myDb => {
return {
connected: true,
db: myDb
}
}
)
.catch(err => {
return {
connected: false,
db: err
}
}
)
}
function isConnected() {
return new Promise(
function(resolve, reject) {
var obj = getDbObject();
if (obj.connected == true) {
console.log('success');
resolve(true);
}
else {
console.log('error');
reject(false);
}
}
)
}
Any help appreciated!
there are multiple ways depends on how your DB is configured. for a standalone (single) instance. You can use something like this
Db.connect(configuration.url(), function(err, db) {
assert.equal(null, err);
if you have a shared environment with config servers and multiple shards you can use
db.serverConfig.isConnected()
Let client be the object returned from MongoClient.connect:
let MongoClient = require('mongodb').MongoClient
let client = await MongoClient.connect(url ...
...
This is how i check my connection status:
function isConnected() {
return !!client && !!client.topology && client.topology.isConnected()
}
This works for version 3.1.1 of the driver.
Found it here.
From version 3.1 MongoClient class has isConnected method. See on https://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html#isConnected
Example:
const mongoClient = new MongoClient(MONGO_URL);
async function init() {
console.log(mongoClient.isConnected()); // false
await mongoClient.connect();
console.log(mongoClient.isConnected()); // true
}
init();
There has been some changes since version 3, isConnected is no longer available in version 4. The correct way of dealing with an ambiguous connection is to just call MongoClient.connect() again. If you're already connected nothing will happen, it is a NOOP or no-operation, and if there is not already a connection you'll be connected (as expected). That said, if you really want to know if you have a connection try something like this:
const isConnected = async (db) => {
if (!db) {
return false;
}
let res;
try {
res = await db.admin().ping();
} catch (err) {
return false;
}
return Object.prototype.hasOwnProperty.call(res, 'ok') && res.ok === 1;
};

how to properly execute custom node module as a function

Getting started with Node.
Put together a custom module, which parses an Excel file into a MongoDB:
exports.excelFileParser = function(fileName){
if(typeof require !== 'undefined') XLSX = require('xlsx');
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://127.0.0.1:27017/my_database';
var workbook = XLSX.readFile('./uploads/' + fileName);
var worksheet = workbook.Sheets[workbook.SheetNames[0]];
var json_conversion = XLSX.utils.sheet_to_json(worksheet);
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
console.log('Connection established to', url);
db.open(function(err, client){
client.createCollection("test_collection", function(err, col) {
client.collection("test_collection", function(err, col) {
{
json_conversion.forEach(function(record) {
col.insert(record, function(err, result) {
if(err) {
console.log(err);
}
else {
}
});
})
}
});
});
});
console.log("finished");
db.close();
}
});
};
In my server.js I require this module as follows:
var excelFileParser = require("excel-file-parser");
At a certain point in my node app, I need to execute the functionality of this module, and pass it a file name to be parsed.
When I try it this way:
excelFileParser(file.fieldname);
I get
TypeError: object is not a function
exception.
What is the proper way to run my module from within server.js?
Lets look at your module:
exports.excelFileParser = function(fileName) {
...
}
When you call require('excel-file-parser') you basically get the exports object.
So to invoke the function you have created you need to call the function:
var myParser = require("excel-file-parser");
myParser.excelFileParser('filename');

Node.js reuse MongoDB reference

I am having trouble understanding node.js.
Example, MongoDB access, here's what I've got (mydb.js):
var mongodb = require('mongodb'),
server = new mongodb.Server('staff.mongohq.com', 10030, {
auto_reconnect: true
}),
db = new mongodb.Db('mydb', server);
function authenticateAndGo(db, handle) {
db.authenticate('username', 'password', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Database user authenticated');
var collection = new mongodb.Collection(db, 'test');
handle(collection);
});
}
function query(handle) {
db.open(function(err, db) {
if( err ) {
console.log(err);
return;
}
console.log('Database connected');
authenticateAndGo(db, handle);
});
};
exports.query = query;
So, if I want to use it later, I would
var mydb = require('./mydb');
mydb.query(function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log(docs);
});
});
But, If I do multiple calls, like so:
var mydb = require('./mydb');
mydb.query(function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log(docs);
});
});
mydb.query(function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log(docs);
});
});
I get an exception:
Error: db object already connecting, open cannot be called multiple times
I think that there is really something fundamental that I do not understand about all this and it is probable that this question is stupid ...
Anyway, all help is welcome.
Thanks in advance.
mydb.js:
var mongodb= require('mongodb'),
server = new mongodb.Server('staff.mongohq.com', 10030, {
auto_reconnect: true
}),
db1 = new mongodb.Db('mydb', server);
// callback: (err, db)
function openDatabase(callback) {
db1.open(function(err, db) {
if (err)
return callback(err);
console.log('Database connected');
return callback(null, db);
});
}
// callback: (err, collection)
function authenticate(db, username, password, callback) {
db.authenticate(username, password, function(err, result) {
if (err) {
return callback (err);
}
if (result) {
var collection = new mongodb.Collection(db, 'test');
// always, ALWAYS return the error object as the first argument of a callback
return callback(null, collection);
} else {
return callback (new Error('authentication failed'));
}
});
}
exports.openDatabase = openDatabase;
exports.authenticate = authenticate;
use.js:
var mydb = require('./mydb');
// open the database once
mydb.openDatabase(function(err, db) {
if (err) {
console.log('ERROR CONNECTING TO DATABASE');
console.log(err);
process.exit(1);
}
// authenticate once after you opened the database. What's the point of
// authenticating on-demand (for each query)?
mydb.authenticate(db, 'usernsame', 'password', function(err, collection) {
if (err) {
console.log('ERROR AUTHENTICATING');
console.log(err);
process.exit(1);
}
// use the returned collection as many times as you like INSIDE THE CALLBACK
collection.find({}, {limit: 10})
.toArray(function(err, docs) {
console.log('\n------ 1 ------');
console.log(docs);
});
collection.find({}, {limit: 10})
.toArray(function(err, docs) {
console.log('\n------ 2 ------');
console.log(docs);
});
});
});
Result:
on success:
Database connected
Database user authenticated
------ 1 ------
[ { _id: 4f86889079a120bf04e48550, asd: 'asd' } ]
------ 2 ------
[ { _id: 4f86889079a120bf04e48550, asd: 'asd' } ]
on failure:
Database connected
{ [MongoError: auth fails] name: 'MongoError', errmsg: 'auth fails', ok: 0 }
[Original Answer]:
You're opening the db multiple times (once in each query). You should open the database just once, and use the db object in the callback for later use.
You're using the same variable name multiple times, and that might've caused some confusion.
var mongodb = require('mongodb'),
server = new mongodb.Server('staff.mongohq.com', 10030, {
auto_reconnect: true
}),
db1 = new mongodb.Db('mydb', server);
function authenticateAndGo(db, handle) {
db.authenticate('username', 'password', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Database user authenticated');
var collection = new mongodb.Collection(db, 'test');
handle(collection);
});
}
function query(handle) {
db1.open(function(err, db2) {
if( err ) {
console.log(err);
return;
}
console.log('Database connected');
authenticateAndGo(db2, handle);
});
};
exports.query = query;
I've changed the above code a little (db1 for the original db, db2 for the opened db). As you can see, you're opening db1 multiple times, which is not good. extract the code for opening into another method and use it ONCE and use the db2 instance for all your queries/updates/removes/...
You can only call "open" once. When the open callback fires, you can then do your queries on the DB object it returns. So one way to handle this is to queue up the requests until the open completes.
e.g MyMongo.js
var mongodb = require('mongodb');
function MyMongo(host, port, dbname) {
this.host = host;
this.port = port;
this.dbname = dbname;
this.server = new mongodb.Server(
'localhost',
9000,
{auto_reconnect: true});
this.db_connector = new mongodb.Db(this.dbname, this.server);
var self = this;
this.db = undefined;
this.queue = [];
this.db_connector.open(function(err, db) {
if( err ) {
console.log(err);
return;
}
self.db = db;
for (var i = 0; i < self.queue.length; i++) {
var collection = new mongodb.Collection(
self.db, self.queue[i].cn);
self.queue[i].cb(collection);
}
self.queue = [];
});
}
exports.MyMongo = MyMongo;
MyMongo.prototype.query = function(collectionName, callback) {
if (this.db != undefined) {
var collection = new mongodb.Collection(this.db, collectionName);
callback(collection);
return;
}
this.queue.push({ "cn" : collectionName, "cb" : callback});
}
and then a sample use:
var MyMongo = require('./MyMongo.js').MyMongo;
var db = new MyMongo('localhost', 9000, 'db1');
var COL = 'col';
db.query(COL, function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log("First:\n", docs);
});
});
db.query(COL, function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log("\nSecond:\n", docs);
});
});
I simply call the open function once directly after the db init:
var mongodb = require('mongodb');
var server = new mongodb.Server('foo', 3000, {auto_reconnect: true});
var db = new mongodb.Db('mydb', server);
db.open(function(){});
After that I do not have to care about that anymore because of auto_reconnect is true.
db.collection('bar', function(err, collection) { [...] };

MongoClient connect() callback is never invoked

No matter what I try callback of MongoClient.connect() is never called. Have tried several alternatives but nothing seems to make the callback function invoked. I am using node.js mongodb driver 2.1.6 and Express routes. Below is the directory structure:
/
node_modules/
exampleServers/
routes/
mongo.js
notes.js
Below is the code for mongo.js which am trying to invoke from notes.js for getting DB connections
var MongoClient = require('mongodb').MongoClient
var state = {
db: null,
}
exports.connect = function(url, done) {
if (state.db) return done()
console.log("***REACHES UPTO HERE");
MongoClient.connect(url, function(err, db) {
console.log("***NEVER REACHES HERE");
if (err) return done(err)
state.db = db
done()
})
}
exports.get = function() {
console.log("state.db" + state.db);
return state.db
}
exports.close = function(done) {
if (state.db) {
state.db.close(function(err, result) {
state.db = null
state.mode = null
done(err)
})
}
}

Resources