The following Tutorial will guide you through creating a simple REST API and CRUD Operations. Our Stack is ExpressJS, Mongoose and MongoDB.

This API will perform CRUD Operations on Data stored in MongoDB. It’s best to start from scratch and try creating this app by yourself. After you tried creating the App with the help of this tutorial, you can go ahead and clone the working Github Repository here. https://github.com/AndreyBulezyuk/nodejsrestapi


Before you continue with this tutorial, please consider signing up for our Mailing List. You’ll get awesome free tutorials, podcasts, free and paid courses into your inbox.


What is REST API and CRUD Operations

REST stands for representation state transfer (wiki) and stands for a software architectural style with a set of constraints which lead to REST Service. Our service (our ExpressJS Server) is an Adapter to another backend service or database. Therefore we call it API.

CRUD is much simpler. The letters stand respectively for Create, Read, Update and Delete. Thus, CRUD stand for a set of operations that allows us to manipulate our states or data (through our REST API).

NPM – Creating the Project

Creating the project is the first step. Create a folder and inside that folder type

npm create

Fill out the following promts that’ll appear after npm create. Then we need to install following packages for our project:

npm install --save express@4.17.1
npm install -g nodemon@1.19.4
npm install --save mongoose@5.7.11

Once there, you should have a file ‘package.json’ in your folder that look like the code below. Note that i added “dev” to “scripts”, where we call nodemon. Nodemon allows us to restart the server automatically as soon as we update a file in our project.

{
  "name": "nodejsboostrap",
  "version": "1.0.0",
  "description": "Basic NodeJS Excercise for German IT Academy (git-academy.com)",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "keywords": [
    "nodejs",
    "germanitacademy",
    "gitacademy",
    "expressjs",
    "nodemon"
  ],
  "author": "Andrey Bulezyuk @ German IT Academy",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "mongoose": "^5.7.11"
  }
}

In schema/ i added a new schema product.js which is pretty similar to the one you will find in the official docs. This is the Object Schema that we will be working with.

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var productSchema = new Schema({
  title:  String,
  author: String,
  body:   String,
  price: Number,
  comments: [{ body: String, date: Date }],
  date: { type: Date, default: Date.now }
});

var Product = mongoose.model('products', productSchema);
module.exports = Product

If you want to learn how to build VueJS Applications that can read from a REST API, take a look at our new VueJS Certification.

Express.JS – REST API Routes

Our Express.js backbone is pretty tiny, only 8 lines of code. We tell Express to use a bodyParser, so we can access the body as a JSON Object. We tell ExpressJS to use our product route and then we start the server.

const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const product = require('./routes/product')

app.get('/', (req, res) => res.send('Hello from German IT Academy!'))
app.use(bodyParser.json())
app.use('/product', product)
app.listen(3000, () => console.log(`Example app listening on port 3000!`))

Just a quick test whether the server is up and ready!

C:\Users\andre>curl localhost:3000
Hello from German IT Academy!

Looks good. Now. Our product route is where all the magic actually happens. All our Documents in MongoDB will be created, read, updated and deleted from this place: routes/product.js.

Now let’s got through each Route (GET, POST, PATCH, DELETE) and see what mongoose method we used to make this work. Note, this is not the ultimate way to do it. Feel free to try out different Methods provided by Mongoose.

The first Route is a GET Route. Which means it only return the Entries in the Database by executing:

router.get('/', async function (req, res) {
    const products = await product.find().exec()
    res.send(products)
})
REST API Request with User Interface for REST API
A simple GET Request, to test whether our API returns the entries from MongoDB.

The POST Route insert new Entries into the MongoDB Database. It uses the data from the Request payload in JSON Format. It’s important to notice that the body payload has to have the right set of Attributes. Meaning that the Request initiator must know what Attributes a Product can/must have.

router.post('/', function (req, res) {
    product.create(req.body)
    res.send('POST Request accepted.')
})

The Patch Route is a bit more complicated. It is cause by the MongoDB Syntax of updating a Document. If we want to update only some Attributes/Keys of a MongoDB Document, we must use the key “$set: {}”. The req.body contains the updated values of attributes/keys for the specified Document. We specify what document to update via the URL Parameter id. Finally we’ll search through MongoDB for an Entry with the corresponding MongoDB “_id”!

router.patch('/:id', async function (req, res) {
    const result = await product.updateMany({
        "_id": String(req.params.id)
    }, { $set: req.body })
    res.send('PATCH Request accepted.')
})

Last and but not least, the Deletion of a Document. The Delete Route. We specify the “_id” of the DOcument in the URL and invoke the Mongoose DeleteMany() Method.

router.delete('/:id', async function (req, res) {
    const result = await product.deleteMany({
        "_id": String(req.params.id)
    })
    res.send('DELETE Request accepted.')
})

That is it, we are done, but, you probably want to see the whole code? Here you go:

var express = require('express')
var router = express.Router()
const mongoose = require('mongoose')
const product = require('../schema/product')
mongoose.connect('mongodb://localhost/nodejsrestapiboostrap', {
    useNewUrlParser: true,
    useUnifiedTopology: true 
});


router.get('/', async function (req, res) {
    const products = await product.find().exec()
    res.send(products)
})

router.post('/', function (req, res) {
    product.create(req.body)
    res.send('POST Request accepted.')
})

router.patch('/:id', async function (req, res) {
    const result = await product.updateMany({
        "_id": String(req.params.id)
    }, { $set: req.body })
    res.send('PATCH Request accepted.')
})

router.delete('/:id', async function (req, res) {
    const result = await product.deleteMany({
        "_id": String(req.params.id)
    })
    res.send('DELETE Request accepted.')
})

module.exports = router

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *