This is the sixth post in a small series on Node.js. In this post, I will take a look at how to use my MongoDB from a Node app.
First, let’s install a driver for MongoDB: node-mongodb-native:
1 |
npm install mongodb |
NPM really make it easy to get going!
Now, in order to connect to MongoDB, do this:
1 2 3 4 5 6 7 8 9 10 |
var mongo = require('mongodb'); var server = new mongo.Server(host_name, port_number, {auto_reconnect: true}); var db = new mongo.Db(database_name, server, {}); db.open(function(err) { // if you need to authenticate, do it here (otherwise just omit the following line): db.authenticate(username, password, function(err) { // now we're ready! }); }); |
This should be done only once when the application starts up.
Then, to access a collection, do this:
1 2 3 |
db.collection(collection_name, function(err, coll) { // do stuff in here }); |
Inside the function above, coll gives you access to do all the usual stuff to a MongoDB collection. To name a few, there’s insert, find, findOne, ensureIndex, count, etc.
As the node-mongodb-native documentation is pretty sparse, I’ve found it useful to open up a Node.js shell and connect with the driver, allowing me to inspect the various objects’ properties and methods, e.g. by inspecting db.__proto__ like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
mogens-heller-grabes-macbook-pro:~ mhg$ node > var util = require('util'); > var mongo = require('mongodb'); > var server = new mongo.Server('localhost', 27017, {auto_reconnect:true}); > var db = new mongo.Db('test', server, {}); > db.open(function(err){}); > console.log(util.inspect(db.__proto__, true, 1)); { logout: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, resetErrorHistory: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, ensureIndex: { [Function] [arguments]: null, [length]: 4, [name]: '', [prototype]: [Object], [caller]: null }, open: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, lastError: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, dropCollection: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, executeDbCommand: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, executeCommand: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, previousErrors: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, removeUser: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, collection: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, dropIndex: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, error: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, createCollection: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, command: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, indexInformation: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, [constructor]: { [Function] [arguments]: null, [length]: 3, DEFAULT_URL: 'mongo://localhost:27017/default', super_: [Object], [name]: '', [prototype]: [Circular], [caller]: null }, lastStatus: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, collections: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, addUser: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, cursorInfo: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, dereference: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, admin: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, createIndex: { [Function] [arguments]: null, [length]: 4, [name]: '', [prototype]: [Object], [caller]: null }, collectionsInfo: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, collectionNames: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, dropDatabase: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, authenticate: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, renameCollection: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, close: { [Function] [arguments]: null, [length]: 0, [name]: '', [prototype]: [Object], [caller]: null }, eval: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null } } |
and coll.__proto__ like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
> db.collection('sessions', function(err, coll) { console.log(util.inspect(coll.__proto__, true, 1)); }); { remove: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, rename: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, save: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, insert: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, group: { [Function] [arguments]: null, [length]: 6, [name]: '', [prototype]: [Object], [caller]: null }, ensureIndex: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, drop: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, findOne: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, checkCollectionName: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, mapReduce: { [Function] [arguments]: null, [length]: 4, [name]: '', [prototype]: [Object], [caller]: null }, insertAll: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, createIndex: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, find: { [Function] [arguments]: null, [length]: 0, [name]: '', [prototype]: [Object], [caller]: null }, count: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, options: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, indexInformation: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, dropIndex: { [Function] [arguments]: null, [length]: 2, [name]: '', [prototype]: [Object], [caller]: null }, distinct: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Object], [caller]: null }, normalizeHintField: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null }, update: { [Function] [arguments]: null, [length]: 4, [name]: '', [prototype]: [Object], [caller]: null }, [constructor]: { [Function] [arguments]: null, [length]: 3, [name]: '', [prototype]: [Circular], [caller]: null }, findAndModify: { [Function] [arguments]: null, [length]: 6, [name]: '', [prototype]: [Object], [caller]: null }, dropIndexes: { [Function] [arguments]: null, [length]: 1, [name]: '', [prototype]: [Object], [caller]: null } } |
Of course this way of barfing functions all over the place is not pretty, but it makes it possible to get a glimpse of what kinds of operations that can be performed on the various objects.
Hey, great article. It’s very useful to start playing with mongo through node.
I have just one problem. I have one doc in a mongohq collection, but when I call:
db.collection(“collection”, function(err, coll) {
coll.find({}, {}, function(err, res) {
console.log( res.items);
});
});
res.items is an empty list. Is there something like “execute” that I need to call in order to get the items?
Thank you!
—Alberteddu
When you call find, the second parameter in the supplied callback (what you call res) is a cursor!
So in order to iterate through the results, you should do something like this:
Wow, thanks. That is really helpful. Again, thank you a lot! 😀
Oh, that’s what I saw before.
“unauthorized db:*** lock type:-1 client:bla bla”
Do you know the meaning of this message? :-O
I don’t know the meaning of that exact message, except that I’d interpret that as some kind of authentication issue.
You’re using MongoHq, right? Try clicking the port number in your list of databases – that will show you how to format a connection string to that database.
Then make sure that <username> and <password> are set to those configured for that database (and not your MongoHq credentials).
You also might want to try connecting with the Mongo Shell fromo your machine – MongoHq shows how to do that as well when you click the port number.
Hope that helps you in diagnosing what’s wrong 🙂
Uhm, this is very strange. Thanks for your suggestion–I can actually connect to mongohq with the shell (and I can find(), each(), etc.), but not with this code.
http://pastie.org/pastes/1754779/text?key=qmorhogmzh4dr9rucssqog
Do you see something wrong? Sorry for bothering you, but Google can’t find anything useful (this time). 🙁
I think your issue can be a race condition between your initialization code and your query code.
Try executing the db.collection stuff from within the callback given to authenticate.
I solved the issue in a small Node sample I have at Github in app.js I open my HTTP server from the authentication callback, ensuring that I don’t do anything before the database connection is ready.
Wow, you saved me. Thanks a lot, that was the problem! 🙂
No problem! Good to hear you got it sorted out 🙂
Thanks mookid, your advise about the race condition solved my problem.
This is exactly what I was looking for. Thanks!