In this article, we will be see how to build a simple and elegant REST based API with MongoDB backend. We are going to use Node.js and Mongoose node module to code a demo application for managing the book resource in MongoDB.
The demo application is based on the following code sample:
The following node modules are used in developing the demo app.
- Mongoose – A node.js MongoDB node module. It’s used for connecting, fetching and saving models in DB.
- Express – It’s a web framework internally make use of core node.js HTTP module. It abstracts and hides the complexities of creating and managing the web server.
- Body-Parser – A body parser is a middleware component used for parsing the incoming data in HTTP Request and makes all the data available as part of the request body. For more information on body-parser, please take a look into the following link.
Let us consider a scenario of managing the book information in MongoDB. We are going to perform the CRUD (create, read, update and delete) operation on the Book model.
We are building a simple REST based API for accessing the book information stored in MongoDB. Later, you will see how to set up routes for accessing the book resource. It’s all part of the express configuration which you will be seeing shortly.
Getting started
Before we code the sample application, we will have to make sure and install the following:
- Mongo DB – We are making use of MongoDB as our backend store. Please download and install the same by the following link.
- Postman – It’s a tiny Google chrome extension that we are using it to test our REST based API’s. Open up chrome and install “Postman” extension. You can install the same from Postman.
Note – After installing, make sure to run the MongoDB, say by executing “mongod.exe” from command prompt.
Defining the Book Model
The following is the code snippet where you can see how we are defining the “Book” model. Firstly, we need to import mongoose Node.js module and then create a schema for our book model. The module exports let's us to access our book model using “require”.
- var mongoose = require('mongoose'),
- Schema = mongoose.Schema;
- var bookSchema = new Schema(
- {
- name: String,
- isbn:
- {
- type: String,
- index: true
- },
- author: String,
- pages: Number,
- description:
- {
- type: String
- },
- added_date:
- {
- type: Date,
- default: Date.now
- }
- });
- var book = mongoose.model('book', bookSchema);
- module.exports = {
- Book: book
- };
Coding the Book Controller Now let us code the book controller to have the following functionality.
- All – Select all books from Mongo DB.
- Select – Select the specified book from Mongo DB.
- Create – Creates a new book based on our Book model.
- Update – Updates the existing book based on the unique ID created by MongoDB.
- Delete – Deletes the book item from MongoDB based on the unique ID created by MongoDB.
Running the demo app
Please download the code sample attached in this article and follow the below instructions.
- Open up command prompt and navigate to the sample directory.
- Type “npm install” and hit enter. It basically reads the package.json to understand the dependencies and install the same so you should be seeing a folder “node_modules” with all dependent node modules.
- Type "node app" and hit enter to run application.
Fetch all Books
Here’s the code snippet of our “all” method. You can notice below, we are getting all “books” in MongoDB without applying the filter conditions. If the fetch goes well, then return all books, else we will be returning a message with the error description.
- var all = function (req, res)
- {
- Book.find(
- {}, function (err, books)
- {
- if (!err)
- {
- res.json(200,
- {
- books: books
- });
- }
- else
- {
- res.json(500,
- {
- message: err
- });
- }
- });
- }
Here’s the snapshot of how getting all the books from Mongo DB works. As of now, we are having only one book and that’s created using HTTP POST which we will be seeing next.
Create Book The following is the code snippet for creating a book via HTTP POST. The function requires two parameters, the request and response. We will be capturing all the book related info from the request body. At first, we are checking whether there exists any book filter by the ISBN number. Create a new book if we don’t have an error or if there are no such existing books in our DB.
In order to create a new book, all we have to do is, create a new instance of our Book model and set all the properties so that we can make a call to “
save” method.
- var create = function (req, res)
- {
- var name = req.body.name;
- var isbn = req.body.isbn;
- var author = req.body.author;
- var pages = req.body.pages;
- var description = req.body.description;
- var added_date = req.body.added_date;
- var book = req.body;
- console.log('Adding Book: ' + JSON.stringify(book));
- Book.findOne(
- {
- isbn: isbn
- }, function (err, exisiting_book)
- {
- if (!err && !exisiting_book)
- {
- var book = new Book();
- book.name = name;
- book.isbn = isbn;
- book.author = author;
- book.pages = pages;
- book.description = description;
- book.added_date = added_date;
- book.save(function (err)
- {
- if (!err)
- {
- res.json(201,
- {
- message: "Book created with name: " + book.name
- });
- }
- else
- {
- res.json(500,
- {
- message: "Could not create a Book. Error: " + err
- });
- }
- });
- }
- else if (!err)
- {
- res.json(403,
- {
- message: "Book already exists! please update instead of creating one."
- });
- }
- else
- {
- res.json(500,
- {
- message: err
- });
- }
- });
- }
Here’s the snapshot of the Postman tool showing how to create a new book by making an HTTP POST Request by passing in the raw book JSON data.
Select Book Let us now see how to select an existing book from MongoDB. The following is the code snippet for the same. We are going to find the book by ID. If we find one and has no errors while fetching the data, then we return the selected book info with the response code 200, else we are going to handle all the error conditions.
- var select = function (req, res)
- {
- var id = req.params.id;
- console.log('Selecting Book: ' + id);
- Book.findById(id, function (err, book)
- {
- if (!err && book)
- {
- res.json(200, book);
- }
- else if (err)
- {
- res.json(500,
- {
- message: "Error loading workout." + err
- });
- }
- else
- {
- res.json(404,
- {
- message: "Book not found."
- });
- }
- });
- }
Here’s the snapshot, where you can see how we are selecting a book by its ID (which is nothing but a unique ID generated by MongoDB).
Update Book The following is the code snippet for updating an existing book in MongoDB. The code must be familiar to you by now. It looks exactly like “
create” functionality. We are going to update the book, if we already have one, else we report an error stating, we are unable to find one.
Note – In order to update the book information, we have to make an HTTP PUT Request passing in the book information as a JSON data in the HTTP Request body.
- var update = function (req, res)
- {
- var name = req.body.name;
- var isbn = req.body.isbn;
- var author = req.body.author;
- var pages = req.body.pages;
- var description = req.body.description;
- var book = req.body;
- console.log('Updating Book: ' + JSON.stringify(book));
- Book.findOne(
- {
- isbn: isbn
- }, function (err, book)
- {
- if (!err && book)
- {
- book.name = name;
- book.isbn = isbn;
- book.author = author;
- book.pages = pages;
- book.description = description;
- book.save(function (err)
- {
- if (!err)
- {
- res.json(200,
- {
- message: "Book updated: " + name
- });
- }
- else
- {
- res.json(500,
- {
- message: "Could not update book. " + err
- });
- }
- });
- }
- else if (!err)
- {
- res.json(404,
- {
- message: "Could not find book."
- });
- }
- else
- {
- res.json(500,
- {
- message: "Could not update book." + err
- });
- }
- });
- }
The following is the snapshot where you can see, we are making an HTTP Put request to update book info.
Remove Book
The following is the code snippet for deleting an existing book in Mongo DB. In order to remove the book, first we have to search one by ID. If we find one, then we are making a call to “
remove” method and then send a message back to the user stating the book has been removed. Make sure to handle all errors while removing the book.
- var remove = function (req, res)
- {
- var id = req.body.id;
- console.log('Removing Book: ' + id);
- Book.findById(id, function (err, book)
- {
- if (!err && book)
- {
- book.remove();
- res.json(200,
- {
- message: "Book removed."
- });
- }
- else if (!err)
- {
- res.json(404,
- {
- message: "Could not find book."
- });
- }
- else
- {
- res.json(403,
- {
- message: "Could not delete book. " + err
- });
- }
- });
- }
Here’s the snapshot of the Postman tool, where you can see we are making an HTTP DELETE Request by passing in the book ID. You can also select “
form-data” from the following option.
Now let us take a look into the express configuration. The following is the partial code snippet where we are creating an “
app” object of type express and then set the port to use a default “
3000”. You can also notice other settings such as to use body parser JSON, method override, router, etc. is all set.
- var app = express();
-
- app.configure(function(){
- app.set('port', process.env.PORT || 3000);
- app.use(express.logger('dev'));
- app.use(bodyParser.json());
- app.use(express.methodOverride());
- app.use(app.router);
-
- app.use(bodyParser.urlencoded({ extended: false }))
- });
-
- app.configure('development', function(){
- app.use(express.errorHandler());
- });
Here’s the code snippet where you can see how we are configuring the routes for HTTP verbs. At first, we need to import and get the “
Book” model. Then we need to import the book controller so we can set the export methods to our express “app” object. We have to explicitly specify the method to be called for GET, POST, PUT, DELETE, etc.
- var Book = require('./models/book').Book;
- var bookController = require('./controller/bookController')(Book);
-
- app.get('/books', bookController.all);
- app.get('/books/:id', bookController.select);
- app.post('/books', bookController.create);
- app.put('/books', bookController.update);
- app.del('/books', bookController.delete);
Here’s how we are creating a MongoDB connection by importing the mongoose node module.
- var mongoose = require('mongoose');
- mongoose.connect('mongodb://localhost/library');
Let us see how to create a HTTP Server to listen to a specific port so it can handle the client request. The following is the code snippet for the same.
- http.createServer(app).listen(app.get('port'), function(){
- console.log("Express server listening on port %s in %s mode.", app.get('port'), app.settings.env);
- });
Conclusion We have seen how to build a simple REST based API for managing the MongoDB entities. There’s a great potential and benefits that one can get in learning and using Node.js to build useful APIs and applications.