Develope Node.js + MongoDB Application with Mongoose
In my previous post, I demonstrated how to perform CRUD (Create, Read, Update, Delete) operations using Node.js and MongoDB API. This tutorial explains how to easily develop Node.js and MongoDB application with Mongoose application by using the Mongoose API. This tutorial assumes that reader has the knowledge on Node.js and MongoDB and knows how to set up the environment for this tutorial. Those who want to read the basic tutorials on Node.js and MongoDB please refer Introduction to Node.js and How to Install MongoDB on Windows.
If you are interested in receiving more updates on Node.js and MongoDB tutorials, please subscribe here.
Here is the overview of the sections covered in this tutorial.
- Introduction to Mongoose API
- Connecting to MongoDB using Mongoose
- Create Schema and Model in Mongoose
- Inserting Data using Mongoose
- Querying the DB using Mongoose
- Updating existing documents
- Deleting existing documents
- Example Application
Mongoose API
Mongoose is an mongodb object modelling API for node.js. Mongoose provides a straight-forward, schema-based solution to modeling your application data and includes built-in type casting, validation, query building, business logic hooks and more, out of the box. (Introduction taken from the Mongoose API Home page)
To use mongoose API in node.js application one would have to download the Node package for mongoose API using the following command: npm install mongoose
and then import the mongoose API package in your node.js application by using the following command: var mongoose = require('mongoose');
Connecting to MongoDB using Mongoose
The below code connects to the MongoDB database named test running on localhost, port 27017.
var dbHost = 'mongodb://localhost:27017/test'; mongoose.connect(dbHost);
After you have connected to the DB, you need to get a connection object. The connection object initially is in pending state and once it goes into open state we can proceed to interact with MongoDB. For this to happen we register a callback to listen to the open event, the below code registers to listen to error and open events fired by the connection.
db.on('error', console.error.bind(console, 'connection error:')); db.once('open', function(){ console.log("Connected to DB"); //do operations which involve interacting with DB. });
Create Schema and Model in Mongoose
We need to create the schema of the document we are going to persist in the DB. While creating the schema we can mention the attributes of the document, the type of the attribute, additional information like whether an index needs to be created for the attribute and so on. In our example our book document would have the following attributes: name, isbn, author, pages. The below is the sample Schema I created for this example:
//Create a schema for Book var bookSchema = mongoose.Schema({ name: String, //Also creating index on field isbn isbn: {type: String, index: true}, author: String, pages: Number });
Using the above schema we create a Model. The API to create model accepts the following: name of the model, name of the schema it has to use to create model class, name of the collection and whether to skip initialization. The below is the code to create Book Model from the schema:
//Create a Model by using the schema defined above //Optionally one can provide the name of collection where the instances //of this model get stored. In this case it is "mongoose_demo". Skipping //this value defaults the name of the collection to plural of model name i.e books. var Book = mongoose.model('Book', bookSchema, "mongoose_demo");
Lets now see how to insert, read, update and delete records using the Model created above. Unlike previous post, in this post I will show you few examples of inserting records, querying for records, editing records and deleting records.
Inserting data using Mongoose
We create an instance of the Model class and then invoke save
method on the instance to save the data to the DB. While invoking the save
method we also provide a callback which gets executed after the save method returns either with an error or after successfully inserting the data. The below code creates two instances of Book model class and saves it to the DB.
//Instantiating the Model - An instance of Model represents a mongodb document var book1 = new Book({ name:"Mongoose Demo 1", isbn: "MNG123", author: "Author1, Author2", pages: 123 }); //Saving the model instance to the DB book1.save(function(err){ if ( err ) throw err; console.log("Book Saved Successfully"); }); var book2 = new Book({ name:"Mongoose Demo 2", isbn: "MNG124", author: "Author2, Author3", pages: 90 }); book2.save(function(err){ if ( err ) throw err; console.log("Book Saved Successfully"); });
Querying the DB using Mongoose
There are multiple APIs which one can use to query the collection in mongoDB, one can find all those APIs here. In this example I use find
API to query the collection. The below code defines a function which queries for documents having less than 100 pages:
var queryBooks = function(){ //Now querying those books which have less than 100 pages //Find API takes in a query condition, attributes in the document to be projected, //callback to be executed when the data is available. Book.find({pages : {$lt:100}}, "name isbn author pages", function(err, result){ if ( err ) throw err; console.log("Find Operations: " + result); }); }
Updating existing documents
Document can be updated by using the update
API as shown below:
var updateBook = function(){ /* Find the book to be updated using the condition and then execute the update passed to the API as the second argument */ Book.update({isbn : {$eq: 'MNG125'}}, {$set: {name: "Mongoose Demo 3.1"}}, function(err, result){ console.log("Updated successfully"); console.log(result); }); }
Deleting existing documents
Documents can be deleted from the collection by using the remove
API and by specifying the condition for selecting the documents to be deleted.
var deleteBook = function(){ /* When callback is not passed, the action is not invoked on the collection until the exec() method is called. In this case I am not passing the callback and instead executing the action by invoking the exec() method. */ Book.remove({isbn:{$eq: 'MNG124'}}).exec(); }
Node.js + MongoDB + Mongoose Example Application
With this I have shown how the CRUD operations can be performed individually. Putting this all together into a working example given below:
var mongoose = require('mongoose'); var dbHost = 'mongodb://localhost:27017/test'; mongoose.connect(dbHost); //Create a schema for Book var bookSchema = mongoose.Schema({ name: String, //Also creating index on field isbn isbn: {type: String, index: true}, author: String, pages: Number }); //Create a Model by using the schema defined above //Optionally one can provide the name of collection where the instances //of this model get stored. In this case it is "mongoose_demo". Skipping //this value defaults the name of the collection to plural of model name i.e books. var Book = mongoose.model('Book', bookSchema, "mongoose_demo"); var db = mongoose.connection; db.on('error', console.error.bind(console, 'connection error:')); db.once('open', function(){ console.log("Connected to DB"); //Instantiating the Model - An instance of Model represents a mongodb document var book1 = new Book({ name:"Mongoose Demo 1", isbn: "MNG123", author: "Author1, Author2", pages: 123 }); //Saving the model instance to the DB book1.save(function(err){ if ( err ) throw err; console.log("Book Saved Successfully"); }); var book2 = new Book({ name:"Mongoose Demo 2", isbn: "MNG124", author: "Author2, Author3", pages: 90 }); book2.save(function(err){ if ( err ) throw err; console.log("Book Saved Successfully"); deleteBook(); }); var book3 = new Book({ name:"Mongoose Demo 3", isbn: "MNG125", author: "Author2, Author4", pages: 80 }); book3.save(function(err){ if ( err ) throw err; console.log("Book Saved Successfully"); queryBooks(); updateBook(); }); }); var queryBooks = function(){ //Now querying those books which have less than 100 pages //Find API takes in a query condition, attributes in the document to be projected, //callback to be executed when the data is available. Book.find({pages : {$lt:100}}, "name isbn author pages", function(err, result){ if ( err ) throw err; console.log("Find Operations: " + result); }); } var updateBook = function(){ /* Find the book to be updated using the condition and then execute the update passed to the API as the second argument */ Book.update({isbn : {$eq: 'MNG125'}}, {$set: {name: "Mongoose Demo 3.1"}}, function(err, result){ console.log("Updated successfully"); console.log(result); }); } var deleteBook = function(){ /* When callback is not passed, the action is not invoked on the collection until the exec() method is called. In this case I am not passing the callback and instead executing the action by invoking the exec() method. */ Book.remove({isbn:{$eq: 'MNG124'}}).exec(); }
And querying for data from the mongo console we get the following:
> db.mongoose_demo.find() { "_id" : ObjectId("55490d87e34c8acc20b5363d"), "name" : "Mongoose Demo 1", "isbn" : "MNG123", "author" : "Author1, Author2", "pages" : 123, "__v" : 0 } { "_id" : ObjectId("55490d87e34c8acc20b5363f"), "name" : "Mongoose Demo 3.1", "isbn" : "MNG125", "author" : "Author2, Author4", "pages" : 80, "__v" : 0 }
Summary
I hope that this tutorial would be very much helpful to understand how Mongoose API can be used for connecting to the MongoDB. It is obvious that with the help of Mongoose Object Data Mapping (ODM) once can write more complex CRUD operations with minimal effort. Please try the above examples write your feedback in the comments section.