BUILD A REST API WITH NODE.JS, EXPRESS.JS AND MongoDB

BUILD A REST API WITH NODE.JS, EXPRESS.JS AND MongoDB

Table of contents

No heading

No headings in the article.

Let's get to it, shall we?

What is a REST API? REST is an acronym for REpresentational State Transfer and it is an architectural standard for building APIs. For your curiosity, you can read more about this here.

Companies open up their applications' data and functionality to external third-party developers, commercial partners, and internal departments through an application programming interface, or API. Through a documented interface, services and products can communicate with one another and benefit from each other's data and functionality. Developers don't need to understand how an API works; they only need to be able to communicate with other products and services using the interface. API usage has exploded in the last decade, to the point where many of today's most popular web applications would be impossible to create without them.

Now we will build a RESTful API that performs basic CRUD operations to manage the patients in a given hospital. We will use node.js, express.js and MongoDB. We will also use mongoose - an elegant mongodb object modeling for node.js to interact with our database. Some of the tools we will use are:

  • VScode.

  • Postman

  • Git and GitHub

First, we go to github.com and create our project. I always like to start my projects with this step so as to make committing my code and pushing it to Github easier.

After this, in VSCode open the integrated terminal and clone the repository we just created.

https://github.com/horyekhunley/patient_tutorial

After this, we can initialize the project with

npm init -y

This creates a package.json file. This file contains metadata of our project and all the dependencies we will use in the project.

{
  "name": "patient-manager",
  "version": "1.0.0",
  "description": "A RESTful api for managing patients' data",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/horyekhunley/patient-manager.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/horyekhunley/patient-manager/issues"
  },
  "homepage": "https://github.com/horyekhunley/patient-manager#readme"
}

Let's get to installing all the packages we will need. We install packages with

npm install express mongoose dotenv joi ip
  • Express: Fast, unopinionated, minimalist web framework for Node.js. It is the most popular framework for building web applications.

  • Mongoose: We have talked about mongoose earlier.

  • Dotenv: Dotenv is a tool that allows you to keep secret stuff separate from your source code. This is handy in a collaborative context (e.g., work or open source) where you don't want to reveal your database login details. Instead, you can distribute the source code and let others write their own .env file.

  • Joi: According to its website, Joi is the most powerful schema description language and data validator for JavaScript. We will use it for the validation of our schema.

  • ip: We will use this to get the ip address of our computer.

After installing all this, we can move on to create a folder structure for our project.

Let us now define what the patient models will look like. Our model will define the patient's name, email, phone number, and diagnosis. We also add validation using Joi.

const mongoose = require('mongoose')
const Joi = require('joi')

const patientSchema = new mongoose.Schema({
  name: {
    type: String,
  },
phone: {
    type: String,
   },
  email: {
    type: String,
  },
  location: {
    type: String,
  },
  diagnosis: {
    type: String,
  },
})

const validate = (patient) => {

    const schema = Joi.object({
        name: Joi.string().min(5).max(50).required(),
        email: Joi.string().min(5).max(255).required().email(),
        phone: Joi.string().min(9).max(50).required(),
        address: Joi.string().min(5).max(50).required(),
        diagnosis: Joi.string().min(5).max(50),

    })
  return schema.validate(patient);
}

const Patient = mongoose.model('Patient', patientSchema)

module.exports = {
  Patient, validate
}
MONGOOSE_URI=mongodb+srv://username:<password>@cluster0.wqmci.mongodb.net/myFirstDatabase?retryWrites=true&w=majority

Let us create the app.js file which is the entry point for the whole application.

// bring in all inputs
const express = require('express')
const mongoose = require('mongoose')
const ip = require('ip')
require('dotenv').config()

const patientRoutes = require('./routes/patient_routes.js')

const app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

//database connection
mongoose.connect(process.env.MONGOOSE_URI).then(() => {
  console.log('MongoDB connected...')
}).catch((err) => {
  console.log('MongoDB conection error', err)
  process.exit
})

app.use('/api/v1/patients', patientRoutes)

const port = process.env.PORT || 5000
app.listen(port, () => {
  console.log(`Server running on port ${ip.address()}:${port}`)
})

Now we move on to define our routes.

const express = require("express");
const {
    getAllPatients, getPatientById, createPatient, updatePatient, deletePatient,
} = require("../controllers/patient_controllers.js");

const router = express.Router();

router.route("/").get(getAllPatients).post(createPatient);

router
    .route("/:id")
    .get(getPatientById)
    .put(updatePatient)
    .delete(deletePatient);

module.exports = router;

Now we move on to create methods for our controllers, now that is where the real action is!

const express = require('express')
const { Patient, validate } = require('../models/patient_model.js')

const router = express.Router();
//to get all the patients in the database, we use the find method and sort all the entries by their name
exports.getAllPatients = async (req, res) => {
    const patients = await Patient.find().sort("name");
    res.send(patients);
};
// now we can get one patient using the id given to each patient by mongodb
exports.getPatientById = async (req, res) => {
    //first validate request
    const { error } = validate(req.body);
    if (error) return res.status(400).send(error.details[0].message);

    const patient = await Patient.findById(req.params.id);

    if (!patient)
        return res.status(404).send("The patient with the given id was not found");

    res.send(patient);
};
//to create new patient data
exports.createPatient = async (req, res) => {
    //first validate request
    const { error } = validate(req.body);
    if (error) return res.status(400).send(error.details[0].message);

    const patient = new Patient({ ...req.body });
    await patient.save();

    res.send(patient);
};
//let's update the patient data
exports.updatePatient = async (req, res) => {
    //first validate request
    const { error } = validate(req.body);
    if (error) return res.status(400).send(error.details[0].message);

    const patient = await Patient.findByIdAndUpdate(
        req.params.id,
        { name: req.body.name },
        { new: true }
    );

    if (!patient)
        return res.status(404).send("The patient with the given id was not found");

        res.send(patient);
};
//now we delete a patient by the id
exports.deletePatient = async (req, res) => {
    //first validate request
    const { error } = validate(req.body);
    if (error) return res.status(400).send(error.details[0].message);

    const patient = await Patient.findByIdAndRemove(req.params.id);
//if the id of the patient does not exist, we handle that error
    if (!patient)
        return res.status(404).send("The patient with the given id was not found");

    res.send(patient);
};

Now we can use Postman to test the endpoints we defined in our routes.

You can check my code on GitHub here github.com/horyekhunley/patient_tutorial. I welcome all thoughts and constructive criticism.

Cheers.