Skip to content

node.js and mongo (using mongoose) tutorial

NoSQL databases came back into the mainstream when developers needed better performance and were ok with giving up the relational aspect of RDBs (unions, joins, etc). NoSQL is said to be easily scalable horizontally, unlike SQL databases. To use the NoSQL datastore MongoDB with your node instance, you need to install:

The mongoDB schema is dynamic, meaning it gets defined every single time you launch your node server.

So to begin, this is how you define a schema:

var Schema = mongoose.Schema
  , ObjectId = Schema.ObjectID;

var Hobby = new Schema({
    name            : { type: String, required: true, trim: true }
});

var Person = new Schema({
    first_name      : { type: String, required: true, trim: true }
  , last_name       : { type: String, required: true, trim: true }
  , username        : { type: String, required: true, trim: true }
  , hobbies         : [Hobby]
  , shoe_size       : Number
  , eye_color       : String
});

Where Schema is a mongoose interface and ObjectId is a MongoDB datatype. Inside Person (called a collection) you can see the different ways you can define SchemaTypes. The [Hobby] is an array or collection of Embedded Documents (which is itself a Schema, must be defined prior to the main schema). Mongoose also comes with validation middleware, so this acts as your server-side data validation (opposed to client side js).

function validateThis(v){
    return v == 'mike';
}
... first_name      : { type: String, required: true, trim: true, validate: [validateThis, 'your name isnt mike'] } ...

Useful reading on Injection in MongoDB.

And to be able to modify Person we need:

var Person = mongoose.model('Person', Person);

And thats about it for designing schemas!

To save/insert data to a schema, we use the .save() function, which has a callback (as all other db interaction calls).

var person_data = {
    first_name: req.params.first
  , last_name: req.params.last
  , username: req.params.username
};

var person = new Person(person_data);

person.save( function(error, data){
    if(error){
        res.json(error);
    }
    else{
        res.json(data);
    }
});

So person_data is the data we have and want to insert, and as you can see it matches the minimum requirements. After creating a new person object, we can save it to the database. By default, the callbacks have an error and data parameters. They return null by default – no error and no data.

To retrieve some data:

Person.find({}, function(error, data){
    console.log(data);
    res.json(data);
});

Where the first parameter of .find() can be a json object such as

{ username: 'mike' }

which acts as

WHERE username="mike"

(mongoose reference).

And to update a document within a collection, I chose to first check to see if there are actually any users with this username. Then we use the callback parameter

person

which is the actual document with username match to perform alterations and save it. There are other ways to do this.

Person.findOne({ username: req.params.username }, function(error, person){
    if(error){
        res.json(error);
    }
    else if(person == null){
        res.json('no such user!')
    }
    else{
        person.hobbies.push({ name: req.params.hobby });
        person.save( function(error, data){
            if(error){
                res.json(error);
            }
            else{
                res.json(data);
            }
        });
    }
});

I think that’s about it, pull or copy/paste the git repo. Let’s start the server:

node app.js

And add a single document by going to the url:

localhost:3001/adduser/michael/mukhin/mmukhin

To view all documents, go to:

localhost:3001/

And to add hobbies to any user:

localhost:3001/addhobby/mmukhin/beer

GIT repo: https://github.com/mmukhin/psitsmike_mongodb_tutorial

Additional reading: NoSQL server-side javascript injection.

Comment Feed

11 Responses

  1. Thanks for this cool example — and for putting the code on github.

  2. how to store query result into variable?

    like below query
    var first;
    Person.count(room, function(error, count){
    return first;
    });
    console.log(first);

    • michael mukhinApril 25, 2012 @ 8:35 amReply

      You need to have a function w/ a callback. Person.count is asynchronous, so the code “console.log” may (will) get executed before the return and the return is in a different scope. So you can do this:

      function personCount(callback) {
      Person.count(room, function(error, count){ callback(error, count); });
      }

      The “callback” is a “a reference to a piece of executable code, that is passed as an argument to other code.” This might help – http://recurial.com/programming/understanding-callback-functions-in-javascript/

  3. Hi michael mukhin

    i want return value from asynchronous function .here I want to store query result into variable.

    var listcounter;

    // define our function with the callback argument

    function personCount(room,callback) {

    listperson.listactivecount(room,’Active’,function(error, gameactivecount){callback( error,gameactivecount);});

    }

    personCount(room, function(error,num) {
    // this anonymous function will run when the
    // callback is called
    listcounter=num;
    console.log(“callback called! ” + num);
    });

    console.log(listcounter);//here i want to display listpersoncount.How can i return listpersoncount .

    plz help me

  4. How would I add and delete hobbies from the person.hobbies object?

  5. You could use “unique : true” to make the username unique through mongoDB (http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique) but be careful with it because it’s throwing an MongoDB error and not a ValidationError from mongoose.

    The tip is to check the error by adding to your model :
    Schema.on(‘save’, function(err, data) {
    //check error there before saving
    });

    Thanks for the great tutorials and nice related docs about injection !

    P.S. : for useless comments, please RTFM first…



Some HTML is OK

or, reply to this post via trackback.

CAPTCHA Image
*

Continuing the Discussion

  1. [...] node.js and mongo (using mongoose) tutorial – michael mukhin [...]