I am Hack Sparrow
Captain of the Internets.

Mongoskin Tutorial with Examples

Mongoskin Tutorial


Mongoskin is probably the most developer-friendly MongoDB driver for Node.js at the moment - it is asynchronous and has a clean looking structure. But its docs are not that developer-friendly (the effort is much appreciated though) - no good examples or explanation; probably because English isn't the author's first language.

After realizing that the Mongoskin docs may take a long time to improve, I decided to personally address the issue by writing a Mongoskin tutorial for all those who are looking for an easy way to integrate MongoDB with Node.js. This is going to be a beginner's tutorial which will guide you through the basics of Mongoskin and should be enough for all basic Node.js-MongoDB interaction.

To give credit where it is due, Mongoskin is built on top of MongoDB Native. The underlying magic behind Mongoskin is MongoDB Native, all Mongoskin does is make the magic wieldier.

If you are not that familiar with MongoDB, I would highly recommend that you first go through this MongoDB tutorial so that you know the basics of MongoDB, and what to expect from Mongoskin.

We will start this tutorial by installing Mongoskin:

$ npm install mongoskin

You may see this message when you install Mongoskin:

To install with C++ bson parser do <npm install mongodb --mongodb:native>

Don't worry too much about it. That's a message from MongoDB Native, and the C++ BSON parser is now actually deprecated as the JavaScript parser has improved a lot. Just disregard that message.

Now let's create a database on the MongoDB server using the mongo shell so that we can work our examples on it. We'll name the database rockband, it is going to be about a bunch of rock bands.

$ mongo
> use rockband
> db.bands.insert({name: 'Hollywood Rose', members: ['Axl Rose', 'Izzy Stradlin', 'Chris Weber'], year: 1984})
> db.bands.insert({name: 'Road Crew', members: ['Slash', 'Steven Adler', 'Duff McKagan'], year: 1984})
> db.bands.insert({name: 'L.A. Guns', members: ['Tracy Guns', 'Paul Black', 'Mick Cripps', 'Nickey Alexander'], year: 1985})
> db.bands.insert({name: "Velvet Revolver", members: ['Scott Weiland', 'Slash', 'Dave Kushner', 'Matt Sorum', 'Duff McKagan'], year: 2002})

In the above mongo commands, we have made four entries to the collection named bands in the database named rockband.

Now it is time to include the Mongoskin module in your script, you do it this way:

var db = require('mongoskin').db('localhost:27017/rockband'); 

That creates an instance of a connection to MongoDB, by default it is connected to the database rockband. I have named the instance db, so as to keep it consistent with the MongoDB's commandline db object. Henceforth all instances of db is a reference to the instance we created here.

Now what if you need to authenticate to connect to the database? Authentication using Mongoskin is easy, just include the auth creds in the instantiation code like this:

var db = require('mongoskin').db('dewey:tehrock@localhost:27017/rockband');

where "dewey" is the username, and "tehrock" is the password.

The rest of the tutorial will show mongo commands and their equivalents in Mongoskin. If you don't know the basics of MongoDB, you will probably find it hard to follow the examples, so make sure you have gone through the MongoDB tutorial I wrote.

To see the existing data in a collection:

> db.bands.find()

In Mongoskin, it's done this way:

db.collection('bands').find().toArray(function(err, result) {
    if (err) throw err;
    console.log(result);
});

We use the toArray() function to convert the Mongoskin cursor to developer-friendly Array.

So what's the non-toArray() way? Here it is:

db.collection('bands').find({}, function(err, result) {
    result.each(function(err, band) {
        console.log(band);
    });
});

result in this case is not an Array but a Mongoskin cursor, you need to use the each() function to iterate through it.

There is another way of do the same, it doesn't use a callback function, looks 'dirtier', and not recommended at all:

var bands = db.collection('bands').find({});
bands.each(function(err, band) {
    console.log(band);
});

To those wondering if there's any difference between find() and find({}), there is no difference. find() is understood as passing an empty object.

To select only one item from a collection:

> db.bands.findOne()

The Mongoskin way:

db.collection('bands').findOne(function(err, result) {
    if (err) throw err;
    console.log(result);
});

Note: we don't convert the result of the above command to Array because there is only one result, if any.

Now let's add another document to the collection:

> db.bands.insert({name: "Guns N' Roses", members: ['Axl Rose', 'Slash', 'Izzy Stradlin', 'Matt Sorum', 'Duff McKagan'], year: 1986});

To do the same in Mongoskin:

db.collection('bands').insert({name: "Guns N' Roses", members: ['Axl Rose', 'Slash', 'Izzy Stradlin', 'Matt Sorum', 'Duff McKagan'], year: 1986}, function(err, result) {
    if (err) throw err;
    if (result) console.log('Added!');
});

I need to replace the member Matt Sorum with Steven Adler. This is how it would be done from the mongo shell:

> db.bands.update({name:"Guns N' Roses"}, {'$pull':{members:'Matt Sorum'}})
> db.bands.update({name:"Guns N' Roses"}, {'$push':{members:'Steven Adler'}})

And this is how it is done from Mongoskin:

db.collection('bands').update({name:"Guns N' Roses"}, {'$pull':{members:'Matt Sorum'}}, function(err) {
    if (err) throw err;
    db.collection('bands').update({name:"Guns N' Roses"}, {'$push':{members:'Steven Adler'}}, function(err) {
        if (err) throw err;
        console.log('Updated!');
    });
});

Notice how the Mongoskin code is quite similar to that of the mongo shell command. Instead of bands, we have collection('bands'), and we pass a callback function; rest of the it is the same. Most of the Mongoskin functions maintain the similarity with mongo commandline as closely as possible, that's the beauty of Mongoskin, if you are familiar with the commandline version, you can almost guess the Mongoskin version of a command. If there are parameters involved, just pass them as you would in the mongo commandline (works for most of the functions).

Now let's how we do some conditional selections in Mongoskin.

To get the band with the name "Road Crew", we'd do this in mongo shell:

> db.bands.find({name:'Road Crew'})

and this in Mongoskin:

db.collection('bands').find({name:'Road Crew'}).toArray(function(err, result) {
    console.log('Band members of Road Crew');
    console.log(result[0].members);
});

If we know that we can expect a single result, we could use the findOne() function instead of find():

db.collection('bands').findOne({name:'Road Crew'}, function(err, result) {
    console.log('Band members of Road Crew');
    console.log(result.members);
});

Tip: db.collection('bands') could be stored in a variable named bands to make our Mongoskin code leaner, so let's do that:

var bands = db.collection('bands');

Now let's do a count() on the collection:

> db.bands.count()
> db.bands.count({year:{$gte:1985}})

In Mongoskin:

bands.count(function(err, count) {
    console.log('There are ' + count + ' bands in the database');
});

bands.count({year:{$gte:1985}}, function(err, count) {
    console.log(count + ' bands were formed in 1985 or later');
});

Now let's try an updating a document:

From the mongo shell:

> db.bands.update({name:'Hollywood Rose'}, {$set:{year:1983}})

Mongoskin code:

bands.update({name:'Hollywood Rose'}, {$set:{year:2000}}, function(err, result) {
    if (!err) console.log('Year updated!');
});

Deleting a record is a no-brainer. The mongo shell way:

> db.bands.remove({name:'Velvet Revolver'})

The Mongoskin way:

db.collection('bands').remove({name:'Velvet Revolver'}, function(err, result) {
    if (!err) console.log('VR deleted!');
});

Tip: you might get confused, was it remove() or delete()? Remember that delete is a JavaScript reserved keyword, it cannot be used as a function or variables name, hence remove() is the one!

In case you are using the default _id generated by MongoDB, and want to select a document by its _id; doing this way won't get you the result:

{_id: '4f5bc53f3d0b5eb764000002'}

This is the right way:

{_id: db.ObjectID.createFromHexString('4f5bc53f3d0b5eb764000002')}

That's it for today. There is more to Mongoskin than the examples I have shown in this tutorial. I will be covering the more technical aspects of Mongoskin in dedicated tutorials rather than including everything here and making it a boring read. Did I miss anything? Want to know anything? Ping me in the comments, if it is within to the scope of this tutorial I will update it from your feedback, else I'll cover them in a more technical Mongoskin tutorial.

20 Responses to “Mongoskin Tutorial with Examples”


  1. I just wanted to thank u for taking the time to put this together. I wanted more control than mongoose but the native driver with all the nested callbacks was a mess. So I started looking at mongoskin but like u said the documentation is rough. In short, u have helped me gain the confidence I needed to use mongoskin. Thanks


  2. Most welcome, bobby.

  3. Coffeeyesplease on February 6th, 2012 at 2:14 pm

    Hiya, great post this really helps when you trying to get started
    How do you handle BinData objects IsoDates from mongoskin
    I know that from the command line I can something like:
    > db.Current.find({“Token”: new BinData(3, “8bL6D5PWkEy3NGki8JnnIw==”)});
    but from mongoskin I get:
    BinData is not defined
    What I am missing? what do I need to include/require()
    Thanks and again great post


  4. Try new db.Binary(buffer[, subtype]). Since Mongoskin is based on MongoDB Native, you should refer the MongoDB Native docs for details you don’t find on the Mongoskin docs.


  5. I am the author of mongoskin, and I am a “Chinese dude”. Thank you.

    Could you help me improve the document on github?


  6. Hi there Gui, you did an excellent job with Mongoskin. I hope you didn’t take offense to the dude thing. Sorry, if you did. I have removed it anyway. Documentation is going to be huge, hopefully I can help you one of these days.


  7. Here again.

    It’s OK to call me Chinese dude, by the way, what’s the mean of dude? :-)


  8. Yo! Dude means a guy, usually a cool one. Keep rocking, bro.

  9. Neil Craig on May 3rd, 2012 at 4:16 am

    Hi

    I wanted to also pass on my thanks for taking the time and care to write this, you just saved me a ton of time fighting the lack of documentation for mongoskin.

    Thanks so much
    Neil


  10. the following error occurs

    Express server listening on port 3000 in development mode

    /Users/ricardo/folder/Projetos/carrier/App/app.js:11
    result.each(function(err, band) {
    ^
    TypeError: Cannot call method ‘each’ of undefined
    at /Users/ricardo/folder/Projetos/carrier/App/app.js:11:12
    at Object.error (//Users/ricardo/folder/Projetos/carrier/App/node_modules/mongoskin/lib/mongoskin/utils.js:4:5)
    at EventEmitter. (//Users/ricardo/folder/Projetos/carrier/App/node_modules/mongoskin/lib/mongoskin/collection.js:72:15)
    at EventEmitter.g (events.js:156:14)
    at EventEmitter.emit (events.js:70:17)
    at EventEmitter. (//Users/ricardo/folder/Projetos/carrier/App/node_modules/mongoskin/lib/mongoskin/collection.js:107:33)
    at EventEmitter.g (events.js:156:14)
    at EventEmitter.emit (events.js:70:17)
    at //Users/ricardo/folder/Projetos/carrier/App/node_modules/mongoskin/lib/mongoskin/db.js:68:20
    at //Users/ricardo/folder/Projetos/carrier/App/node_modules/mongoskin/lib/mongoskin/db.js:81:9


  11. Marcedo, looks like the result object is ‘empty’. try debugging it.


  12. Just wanted to say thanks – these examples are great :)


  13. Hi Sosh. Welcome, and all the best to you!


  14. Does anyone have an example of how to write a test using mocha on a simple operation using mongoskin? I have raise this question here too: http://stackoverflow.com/questions/11977172/sample-mongoskin-mocha-test. I hope no one objects. :)


  15. thanks a lot for putting this up! :)


  16. Most welcome, noder.


  17. Nice introduction to Mongoskin. One nit: while delete is in fact a reserved word in JavaScript, it can be used as part of an IdentifierName. For example, the following snippet is legal:

    var foo = {delete: “bar”};
    console.log(foo.delete);


  18. @Alvaro, indeed you can. But I would recommend leaving the keywords alone.


  19. Hey, nice writeup. I’ve been using the native driver and you’re right, it’s clumsy. Mongoskin is exactly what it should have been in the first place. Too bad that it wasn’t built that way in the first place.

    Anyway, the problem I have with Mongoskin is that it looks like it’s not being maintained. There are some recent sporadic commits but not from the original author. There are also a bunch of outstanding issues and it doesn’t look like anyone’s taking an interest in closing them. I would like to make use of it in my latest production code but can’t commit to relying on an abandoned library.

    I was wondering if you have any other information as to the status of this library or how well it works in practice.


  20. Thanks for this Captain, very usefull.

    Mongoskin, too many opened tickets, poor documentation, not maintened, no “JOIN” helper, i’ve personaly switched to Mongoose.

Make a Comment