MongoDb driver in nodejs does not call open function callback - node.js

In the following code the function passed to the open function never runs, then the istruction console.log('open!') in the following code never runs:
var mongo = require("mongodb");
var Db = mongo.Db;
var connection = mongo.Connection;
var Server = mongo.Server;
var client = new Db('test', new Server("localhost", 27017, {}));
var test = function (err, collection) {
collection.insert({a:2}, function(err, docs) {
collection.count(function(err, count) {
test.assertEquals(1, count);
});
// Locate all the entries using find
collection.find().toArray(function(err, results) {
test.assertEquals(1, results.length);
test.assertTrue(results[0].a === 2);
// Let's close the db
client.close();
});
});
};
client.open(function(err, p_client) {
console.log('open!');
client.collection('test_insert', test);
});
From the log I see that the connection is accepted:
Sun March 11 16:52:01 [initandlisten] accepted connection from 127.0.0.1:61875 # 1
Mongodb great works from interactive shell.
can someone tell me any suggestion?
thank you!

Copy/paste this...it should work without any problems:
var client = new Db('test', new Server("localhost", 27017, {}), {});
client.open(function(err, client) {
console.log('open!');
}
Also, don't forget to authenticate after opening the connection.
var client = new Db('test', new Server("localhost", 27017, {}), {});
client.open(function(err, client) {
console.log('open!');
client.authenticate('admin', 'admin', function(err, result) {
// Authenticated
});
}

Related

"Collection is not defined" error on insert with mongodb

I am using mongodb in a nodejs app I am currently writing.
Upon running an insert in my code, I get the following error back: ReferenceError: collection is not defined at /home/safeuser/lunchand/routes/talktomongo.js:17:7
As far as I can tell from docs, simply running insert in a collection should create it! If I open mongo manually in my terminal and run show dbs I also never see lunchand in the list of dbs, just local and admin.
Here's the code I'm using. Line 17 is where the collection.insert is. Any help would be greatly appreciated.
//Declarations
var mongo = require('mongodb'),
Server = mongo.Server,
Db = mongo.Db,
server = new Server('localhost', 27017, {auto_reconnect: true}),
db = new Db('lunchand', server);
//Open database
db.open(function(_err, _db) {
if(!_err) {
console.log("Connected to lunchand DB");
db.collection('lunchers', {strict: true}, function(_err, _collection) {
if(_err) {
console.log("Lunchers collection doesn't exist! Let's fix that!");
var testLuncher = {username:"username",pwd:"password",officeLocation:"Office Location",teams:"teams",shark: true};
db.collection('lunchers', function(_err, _collection) {
collection.insert(testLuncher, {safe:true}, function(_err, _result) {});
});
} else {
console.log("Oh it exists");
}
});
} else {
console.log("Error Connecting to Station DB: " + _err);
}
});
try to add the name of the collection to the object something like this:
db.collection("lunchers").insert(testLuncher,function(err, element){
console.log("element inserted");
});
probably your code should look like:
var mongo = require('mongodb'),
Server = mongo.Server,
Db = mongo.Db,
server = new Server('localhost', 27017, {auto_reconnect: true}),
db = new Db('lunchand', server);
//Open database
db.open(function(_err, _db) {
if(!_err) {
db.collection('lunchers', {strict: true}, function(_err, _collection) {
if(_err) {
var testLuncher = {username:"username",pwd:"password",officeLocation:"Office Location",teams:"teams",shark: true};
db.collection("lunchers").insert(testLuncher,function(err, element){
console.log("element inserted");
});
} else {
console.log("Oh it exists");
}
});
} else {
console.log("Error Connecting to Station DB: " + _err);
}
});
I would guess that line 17 should actually be either db.collection.insert(... or _collection.insert(...

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();

node.js application - integrate mongodb in appfog

I am starting to use appfog services in order to host node application.
I am getting trouble trying to use mongodb in my application.
In you tutorial here: https://docs.appfog.com/services/mongodb#walkthrough it is written to connect mongodb like this:
require('mongodb').connect(mongourl, ...
while mogourl is the url generated by the generate_mongo_url function.
The problem is that I am using newer api (I think) and I cannot pass url to the open method. This is how I am using mongodb:
var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) { ...
Where and how can I use the generated mongourl? How can I pass the credentials and the mongo variable used in generate_mongo_url function?
UPDATE
According to #mjhm suggestion, this is my open function:
var mongoService = null;
if(process.env.VCAP_SERVICES){
var env = JSON.parse(process.env.VCAP_SERVICES);
mongoService = env["mongodb-1.8"][0]["credentials"];
} else {
mongoService = {
"hostname": "localhost",
"port": 27017,
"isLocal": true,
"username": "",
"password": "",
"name": ""
};
}
this.mongoClient.open(function(err, mongoClient) {
if (!err) {
console.log("Open DB Success");
var db = mongoClient.db(DB_NAME);
if (!mongoService.isLocal) {
db.authenticate(mongoService.username,
mongoService.password, function (err, result) {
if (!err) {
console.log("Authenticate DB Success");
doAction();
} else {
console.log("Authenticate DB Error: " + err);
}
});
} else {
doAction();
}
} else {
console.log("Open DB Error: " + err);
}
});
When I am running this code on appfog, I am waiting a lot of time (more then 20 seconds) and then I get:
$ curl myappname.eu01.aws.af.cm/list
curl: (52) Empty reply from server
Any idea what is wrong?
What you are looking for is the MongoClient.connect function
http://mongodb.github.com/node-mongodb-native/driver-articles/mongoclient.html#mongoclient-connect
It takes the url you are talking about.
the URL where your client / driver wants to connect to was 'localhost'. I replaced it with a
variable mongoUrl
var mongoClient = new MongoClient(new Server(mongoUrl, 27017));
You need to authenticate after opening the database. The way to think of it is that authentication happens against the database not the connection, so as you discovered the generate_mongo_url function isn't very useful.
For example:
var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
var db = mongoClient.db('test');
db.authenticate('me', 'mypwd', function (err, result) {
var coll = db.collection('query_example3');
coll.find().toArray(function(err, result) {
console.log(result);
process.exit(0);
});
});
});

Mongodb (mongolab) Node.js finding nothing on a collection

I'm a big Node.js and Mongo newbie, so please be gentle.
So here's my Node.js app:
var mongo = require('mongodb');
var Server = mongo.Server;
var Db = mongo.Db;
var server = new Server('hostname.mongolab.com', 666, {auto_reconnect : true}, {w:0, native_parser: false});
var db = new Db('dbName', server, {safe:true});
db.open(function(err, client) {
if(err) { return console.dir(err); }
client.authenticate('mongolabUser', 'mongolabUserPassword', function(authErr, success) {
if(authErr) { return console.dir(authErr); }
var stream = client.collection('myCollection').find({}).stream();
stream.on('data', function(item) {console.log("Do something with item"); });
stream.on('end', function() {console.log("Empty!");});
});
db.close();
});
Through prodigious use of debugger statements, I've come to the conclusion that the client.authenticate doesn't seem to be run. It looks like it's about to execute that line, but then just leapfrogs over it and goes straight to db.close().
But that's just the first of my problems. At some point prior, I was able to connect in to the database and authenticate, but my user was no retrieving anything in the find({}) command. I tried all sorts of ways, and streams are my latest attempt before deciding to give up on it for now.
Mongolab seems to be on v2.0.7, my mongo installation is v2.2.1. When I use the command line tool to log in as mongolabUser and execute a command like db.myCollection.find(), I get everything in my collection, so it can't be an issue with permissions.
Any advice/suggestions?
client.authenticate() is asynchronous, so the line that calls it starts the authentication, but doesn't wait for the server to respond before moving on to executing the next line, db.close(). So by the time the server responds the connection has been closed by the client.
Does moving the db.close() inside the event handler for stream.end help?
var mongo = require('mongodb');
var Server = mongo.Server;
var Db = mongo.Db;
var server = new Server('hostname.mongolab.com', 666, {auto_reconnect : true}, {w:0, native_parser: false});
var db = new Db('dbName', server, {safe:true});
db.open(function(err, client) {
if(err) { return console.dir(err); }
client.authenticate('mongolabUser', 'mongolabUserPassword', function(authErr, success) {
if(authErr) { return console.dir(authErr); }
var stream = client.collection('myCollection').find({}).stream();
stream.on('data', function(item) {console.log("Do something with item"); });
stream.on('end', function() {
console.log("Empty!");
db.close();
});
});
});

why is my nodeunit test of mongodb not finishing?

I am writing nodeunit tests for operations around a mongodb. When I execute my test with nodeunit (nodeunit testname.js), the test runs through and goes green but the nodeunit command line doesn't return (I need to hit ctrl-c).
What am I doing wrong? Do I need to close my db connection or the server or is my test wrong?
Here is a cutdown sample test.
process.env.NODE_ENV = 'test';
var testCase = require('/usr/local/share/npm/lib/node_modules/nodeunit').testCase;
exports.groupOne = testCase({
tearDown: function groupOneTearDown(cb) {
var mongo = require('mongodb'), DBServer = mongo.Server, Db = mongo.Db;
var dbServer = new DBServer('localhost', 27017, {auto_reconnect: true});
var db = new Db('myDB', dbServer, {safe:false});
db.collection('myCollection', function(err, collectionitems) {
collectionitems.remove({Id:'test'}); //cleanup any test objects
});
cb();
},
aTest: function(Assert){
Assert.strictEqual(true,true,'all is well');
Assert.done();
}
});
Michael
Try putting your cb() within the remove() callback after you close you connection:
var db = new Db('myDB', dbServer, {safe:false});
db.collection('myCollection', function(err, collectionitems) {
collectionitems.remove({Id:'test'}, function(err, num) {
db.close();
cb();
});
});
You need to invoke cb function after the closure of db (during the tearDown):
tearDown: function(cb) {
// ...
// connection code
// ...
db.collection('myCollection', function(err, collectionitems) {
// upon cleanup of all test objects
db.close(cb);
});
}
This works for me.

Resources