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);
});
});
});
Related
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(...
I am working on a nodejs / mongodb app using 'mongodb' module. The app is launched with
node main.js
In main.js, I connect to the db and keep the connection in the 'db' global variable. 'db' is then used in inner methods of 'server'. I want to avoid having 'db' as a global variable but did not found the correct way to do.
My current main.js:
var server = require('./lib/server');
var MongoClient = require('mongodb').MongoClient;
var Server = require('mongodb').Server;
var mongoClient = new MongoClient(new Server(HOST, PORT));
db = null;
// Database connection
mongoClient.open(function(err, mongoClient) {
if(!err){
// Database selection
db = mongoClient.db(DB);
// Launch web server
server.start(); // usage of 'db' in this part
} else {
console.log(err.message);
process.exit(1);
}
});
Any idea of a cleaner way ?
UPDATE
I finally created a module in connection.js:
var config = require('../config/config');
var url = 'mongodb://' + config.db.host + ':' + config.db.port + '/' + config.db.name;
var MongoClient = require('mongodb').MongoClient;
var db = null;
module.exports = function(cb){
if(db){
cb(db);
return;
}
MongoClient.connect(url, function(err, conn) {
if(err){
console.log(err.message);
throw new Error(err);
} else {
db = conn;
cb(db);
}
});
}
Each time I need to get the connection I call:
var connection = require('./connection');
connection(function(db){
// doing some stuff with the db
});
This is working very well.
Any potential failure with this approach ?
I typically include a project utilities file that contains a number of these things, just to make it easy. It functions as a pseudo global, but without many of the usual problems globals entail.
For example,
projectUtils.js
module.exports = {
initialize: function(next){
// initialization actions, there can be many of these
this.initializeDB(next);
},
initializeDb: function(next){
mongoClient.open(function(err, mongoClient) {
if(err) return next(err);
module.exports.db = mongoClient.db(DB);
next();
});
}
}
app.js
var projectUtils = require('projectUtils');
// (snip)
projectUtils.initialize(function(err) {
if(err) throw err; // bad DB initialization
// After this point and inside any of your routes,
// projectUtils.db is available for use.
app.listen(port);
}
By using an asynchronous initialize() function, you can be sure that all database connections, file I/O, etc., are done before starting up the server.
You can create a wrapper something like a provider and put it in provider.js, for instance.
Provider = function (db_name, host, port, username, password) {
var that = this;
var conn = generate_url(db_name, host, port, username, password); // you need to implement your version of generate_url()
MongoClient.connect(conn, function (err, db) {
if (err) {
throw err;
}
that.db = db;
});
};
//add the data access functions
Provider.prototype.getCollection = function (collectionName, callback) {
this.db.collection(collectionName, collectionOptions, callback);
};
exports.Provider = Provider;
This is how you use the provider:
var db = new Provider(db_name, host, port, username, password);
db.getCollection('collection name', callback);
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();
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();
});
});
});
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
});
}