For developers who are new or switching to the node based API. I’m going to development and show how to develop a REST API with CRUD create, read, update, and delete endpoints using Node.js, express.js and the very popular Mongoose object document modeler (ODM) to interact with MongoDB.
Restful API – Representational State Transfer API is very important part of web application now, and no one can be a software developer, full stack developer or backend developer without writing the API using mongoDb, Express.Js and Node.Js.
API is an acronym for Application Programming Interface which has become an integral part of software development. “It is a set of of clearly defined methods of communication between various components” — Wikipedia.
Required applications: How to Build a RESTful API Using Node.js, Express, and MongoDB
- Node.JS
- Express.JS
- MongoDB
- Mongoose ODM
- Postman Client
- IDE (visual studio or any)
Before Creating a REST API using Node.js, Express, and MongoDB. I am going to highlight the scope of the API end points. I will create 5 endpoints using Express.Js, Node.Js, MongoDb, Mongoose. The commonest implementation of RESTFul web service is JSON Javascript Object Notation API and that is what we will be working with in this tutorial.
- POST /posts – Create a new Post
- GET /posts – Retrieve all Posts
- GET /posts/:postId – Retrieve a single Post with postId
- PUT /posts/:postId – Update a Post with postId
- DELETE /posts/:postId – Delete a Post with postId
Structuring Your API:
Structuring the application is like the pillar of an application. More strong the pillar, more strong the application. Any future developers can work on the app easily and enhance the application. If structure is not good then other developers will not understand what you’re building nor will they be able to figure out how to build on top of it.
You can use npm init also to bootstrap the structure. I have created a standard structure which is heavily used in application and have a scope of good maintainability and can be easily extend.
Package.json: store the node.js project configuration including dependencies. Installed node packages are located in node_modules and we should not modify anything in that directory rather we should exclude with gitignore when we are pushing to a remote repository. In our package.json, we defined server.js as our app’s entry point. Create your own package.json file and add below details.
{
"name": "seoinfotech-post-app",
"version": "1.0.0",
"description": "POST App using mean stack.",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Express",
"RestAPI",
"MongoDB",
"Mongoose",
"Posts"
],
"author": "seoinfotech",
"license": "MIT",
"dependencies": {
"body-parser": "^1.18.2",
"express": "^4.16.3",
"mongodb": "^3.2.7",
"mongoose": "^5.0.11"
}
}
Here we have added dependencies required and other details. main entry file as server.js.
Create a server.js file and copy all code inside the file.
/**
* main file: server.js
* author: seoinfotech
*/
const express = require('express');
const bodyParser = require('body-parser');
// create express app
const app = express();
// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }))
// parse requests of content-type - application/json
app.use(bodyParser.json())
// Configuring the database
const dbConfig = require('./config/database.config.js');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
// Connecting to the database
mongoose.connect(dbConfig.url, { useNewUrlParser:true })
.then(() => {
console.log("Successfully connected to the database");
}).catch(err => {
console.log('Could not connect to the database. Exiting now...');
process.exit();
});
// define a simple route
app.get('/', (req, res) => {
res.json({"message": "Welcome to application."});
});
// Require Notes routes
require('./app/routes/post.routes.js')(app);
// listen for requests
app.listen(3000, () => {
console.log("Server is listening on port 3000");
});
Create model: create a new model file post.model.js file inside app/models/ folder and copy the code.
/**
* model: Post
* author: seoinfotech
*/
const mongoose = require('mongoose');
const PostSchema = mongoose.Schema({
title: String,
content: String
}, {
timestamps: true
});
module.exports = mongoose.model('Post', PostSchema);
Create Controller: create a new controller file post.controller.js file inside /app/controllers/ folder and copy the code. Controller implements the endpoints methods like create, update, delete etc.
/**
* controller - all logic are here
* author: seoinfotech
*/
const Post = require('../models/post.model.js');
// Create and Save a new Post
exports.create = (req, res) => {
// Validate request
if(!req.body.content) {
return res.status(400).send({
message: "Post content can not be empty"
});
}
// Create a Post
const post = new Post({
title: req.body.title || "Untitled Post",
content: req.body.content
});
// Save Post in the database
post.save()
.then(data => {
res.send(data);
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while creating the Post."
});
});
};
// Retrieve and return all posts from the database.
exports.findAll = (req, res) => {
Post.find()
.then(posts => {
res.send(posts);
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving posts."
});
});
};
// find on some criteria
/*Post.findOne({ title: 'seo' }, function (err, data) {
if(err) {
res.status(500).send(err);
}
res.send(data);
});*/
// Find a single Post with a postId
exports.findOne = (req, res) => {
Post.findById(req.params.postId)
.then(post => {
if(!post) {
return res.status(404).send({
message: "Post not found with id " + req.params.postId
});
}
res.send(post);
}).catch(err => {
if(err.kind === 'ObjectId') {
return res.status(404).send({
message: "Post not found with id " + req.params.postId
});
}
return res.status(500).send({
message: "Error retrieving post with id " + req.params.postId
});
});
};
// Update a post identified by the postId in the request
exports.update = (req, res) => {
// Validate Request
if(!req.body.content) {
return res.status(400).send({
message: "Post content can not be empty"
});
}
// Find post and update it with the request body
Post.findByIdAndUpdate(req.params.postId, {
title: req.body.title || "Untitled Post",
content: req.body.content
}, {new: true})
.then(post => {
if(!post) {
return res.status(404).send({
message: "Post not found with id " + req.params.postId
});
}
res.send(post);
}).catch(err => {
if(err.kind === 'ObjectId') {
return res.status(404).send({
message: "Post not found with id " + req.params.postId
});
}
return res.status(500).send({
message: "Error updating post with id " + req.params.postId
});
});
};
// Delete a post with the specified postId in the request
exports.delete = (req, res) => {
Post.findByIdAndRemove(req.params.postId)
.then(post => {
if(!post) {
return res.status(404).send({
message: "Post not found with id " + req.params.postId
});
}
res.send({message: "Post deleted successfully!"});
}).catch(err => {
if(err.kind === 'ObjectId' || err.name === 'NotFound') {
return res.status(404).send({
message: "Post not found with id " + req.params.postId
});
}
return res.status(500).send({
message: "Could not delete post with id " + req.params.postId
});
});
};
Create routes: create a file post.routes.js inside /app/routes/ folder and copy the below code.
/**
* Route file
* author: seoinfotech
*/
module.exports = (app) => {
const posts = require('../controllers/post.controller.js');
// Create a new Post
app.post('/posts', posts.create);
// Retrieve all Posts
app.get('/posts', posts.findAll);
// Retrieve a single Post with postId
app.get('/posts/:postId', posts.findOne);
// Update a Post with postId
app.put('/posts/:postId', posts.update);
// Delete a Post with postId
app.delete('/posts/:postId', posts.delete);
}
here I have created 5 routes
- POST /posts – Create a new Post
- GET /posts – Retrieve all Posts
- GET /posts/:postId – Retrieve a single Post with postId
- PUT /posts/:postId – Update a Post with postId
- DELETE /posts/:postId – Delete a Post with postId
Create config: Now create the config file which will keep the mongodb database information. add file database.config.js in /config folder.
/**
* database config
* author: seoinfotech
*/
module.exports = {
url: 'mongodb://localhost:27017/si-posts'
}
Here si-post is database name. 27017 is by default port on which mongoDB run.
.gitignore: git file to ignore. (optional)
README.md: git file, used to provide information(optional)
Now we are good to go. Change directory to root. and run the install command npm install, it will install all the dependencies as given in package.json. All the installation will be done in node_modules folder at root.
npm install
Now start the server using command
node server.js
Server is listening on port 3000
Successfully connected to the database
Check whether application is running or not. Open localhost:3000 in chrome or any browser. It should say like
Check Api’s we have created. Open postman client and create a Post.
AddNew: {“title”: “Java”, “content”: “Java is open source”}. Use our POST /posts api
New Record is crated with _id = 6006a93aec474f31443bc7ea. Now add some more record.
{
“title”: “angular”,
“content”: “my angular book”
}
{
“title”: “react”,
“content”: “my react book”
}
Update : PUT /posts/6006a93aec474f31443bc7ea it will update the above record.
You can see record is updated.
GetAll: Get all record using POST /posts api.
Delete: Delete using DELETE /posts/:postId api
Post deleted successfully.
So this is a quick tutorial on Building a RESTful API Using Node.JS and MongoDB. Please comment if you are looking more on this topic. We will update the tutorial. code