Employee Viewer API - Node, Express, Mongo - Part 2

create, read, update or delete employees using this API

Employee Viewer API - Node, Express, Mongo - Part 2

This is Part 2 of the series, you can navigate to Part 1 as this will contain basics of what I am going to build.

Introduction

Thank you for so much views and likes for my Part 1 of the series ๐Ÿ‘.

Previously, we saw about the setup of the basics of the REST API. We also created a very basic boilerplate code and added a GET route which returns a very simple message. We also saw about how we are going to structure the models and the routes using diagrams. We will be continuing that in this post.

Table Of Contents

  1. Setup of the REST API โœ”๏ธ
  2. Adding Routes and Adding Models - ( You are here ๐Ÿšฉ )
  3. Configure and Adding Images for Profile Pic
  4. Adding Controllers
  5. Testing using Postman
  6. Deploying REST API

Connect express app to Mongo DB

In order for our models and routes to work properly we will add a connection url to connect to mongo db. We will be using the cloud version on mongo DB, the Mongo Atlas.

Navigate to this link to login or sign up your account. Once you click the link you will be redirected to a website like below:

image.png

You can sign up for an account if you are a new user, the onboarding process is pretty straight-forward. If you are already a user, you can login using your credentials.

Once you are in, You need to create an organization first, this is basically your overall company name, you can name it anything you want. Inside each organization you are allowed to create 5 projects. Each project will have a database/cluster associated with it. You have an option for only 1 free cluster/database per project.

Now let's create a new database, I will choose the options like below:

image.png

Note that you need to select Free Forever option so that you don't pay.

I am choosing a shared cluster because this is just a api for learning and not for production. You can click on Create Cluster if you are happy with the options selected.

It will navigate to the cluster dashboard, where it will create the cluster and all other settings. You need to wait for a while until the cluster is setup.

image.png

Once your cluster is setup it will look like below:

image.png

Before we can connect to our DB, we need to setup two things:

  1. Database Access
  2. Network Access

Database Access

Navigate to the Database Access in the side menu. This is to add the user to access the Database. You can assign users with different roles. We will be adding 1 user as an admin.

image.png

Click on Add New Database User. A modal will open like below

image.png

You can keep the Authentication method as password as I am going to use the Password option. You can experiment with other Authentication methods if you are interested.

In the Password Authentication section add your username and password or you can also auto-generate the password if needed. Take a note of your username and password. This will be needed when we connect the API with mongo atlas.

Next in Database User Privileges make sure you select the Read and Write to any database from the dropdown. There are also other built-in roles and even more specific advanced roles.

Once you are done with credentials, Click Add User. The Cluster will make the changes which will take a while. Now when its setting the new changes let us also add some network access as well. We need Network access when we need to connect to the Atlas from any server we have.

Network Access

Navigate to Network Access from the side menu, Click on Add IP Address

image.png

In the below modal, you can see 2 buttons

  1. Add Current IP address
  2. Allow Access From Anywhere

image.png

For this tutorial I am going to Allow Access From Anywhere. Once you are done with that you can click on Confirm and it will apply the changes to the Cluster. While we wait let's make some changes to our folder structure.

Folder structure setup

I want to change my folder structure a bit before proceeding to creating routes. Folder structure becomes really important even though your app may not be big right now, but later on you may add features and you have to waste time then to reshuffle files in and out of folders. So it's always wise to keep a fixed folder structure and let your team know about what structure needs to be followed.

Below is the folder structure I want to keep:

image.png

You can keep the above folder structure if you or you can follow your own folder structure that is comfortable to you.

Lets create a folder named api in the root of the folder. Inside api we will have 3 folders:

  1. controllers
  2. models
  3. routes

We will also add .env file to access our mongo url we may need later. In your root of the folder create a file named .env. We will add values inside this file later.

๐Ÿšจ๐Ÿšจ๐Ÿšจ Do not commit the .env file in your version control, this is strictly to be only for server side and never to be shared to public ๐Ÿšจ๐Ÿšจ๐Ÿšจ

Connecting MongoDB with Express

Now that our Mongo Atlas is ready we can connect it to our app. Go to your Mongo Atlas dashboard like below

image.png

Click on the Connect button, a modal will open like below

image.png

Select Connect you application method as this will provide us with the mongo url that we can directly use with the mongoose library we installed in Part 1.

image.png

Copy that url and paste it inside the .env file we made earlier. Like

MONGO_URL=mongodb+srv://<username>:<password>@employee-viewer-db.isds9.mongodb.net/<dbname>?retryWrites=true&w=majority

Add your username, password and the dbname you wish to keep. I will use my dbname as test.

In order to use the .env values in our app globally we need to install a package named dotenv from the npm repository.

if your server is running, stop and run the following

npm install dotenv

Configure index.js to use the env variables

Open your index.js add the following to top of the file above everything.

require('dotenv').config()

Now that you have added this line you can use the process.env.MONGO_URL to connect to the mongo db.

Connecting to Mongo DB


Open index.js and first we need to import the mongoose package. We will use the connect function and pass it our MONGO_URL variable we set it in the .env file.

require("dotenv").config();
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const mongoose = require("mongoose");
const app = express();

mongoose.connect(
  `${process.env.MONGO_URL}`,
  {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  },
  function (err, client) {
    if (err) {
      console.log(err);
    }
    console.log("connected!!!");
  }
);

app.use(cors());
app.use(morgan("dev"));
app.use(express.json());

app.get("/", (req, res) => {
  res.status(200).json({
    message: "API is Working",
  });
});

app.listen(9000, () => {
  console.log("Express App Running http://localhost:9000");
});

Once you run the above file, you will see an output like this,

image.png

Adding Models

Before we move to creating routes we first need to configure models. As I illustrated in the previous article about our Employee Model. You can go to Part 1 to see the information regarding the model.

Create a file named employee.js inside the models folder.

employee.js

const mongoose = require("mongoose");
const skills = new mongoose.Schema({ name: "string" });
const employeeSchema = mongoose.Schema({
  _id: mongoose.Schema.Types.ObjectId,
  name: { type: String, required: true },
  age: { type: Number, required: true },
  profile_pic: { type: String, default: null },
  designation: { type: String, default: "-" },
  organization: { type: String, default: "-" },
  date_of_join: { type: String, default: new Date().toDateString() },
  experience: { type: String, default: "-" },
  skills: [skills],
});

module.exports = mongoose.model("Employee", employeeSchema);

Now let's create our first route and try to create an employee.

Adding Routes


We saw in the Part 1 that we have the following routes we need to add.

API Endpoints

We will need to create,read,update and delete information about the employees. We also need to add the authentication where only authenticated employees can edit, delete and create. We will get to authentication later.

GET Requests - Public Visibility

  1. GET - All Employees - /all
  2. GET - Single Employee(by ID) - /all/:id

POST Requests

  1. POST - Create Single Employee - Private Visibility - /create

PUT Requests - Private Visibility

  1. PUT - Edit Single Employee(by ID) - /edit/:id

DELETE Requests - Private Visibility

  1. DELETE - Delete Single Employee(by ID) - /delete/:id

For now we just need to add 1 file inside the routes folder. We will add employee.js inside the routes folder.

Let's add the code we need for the employee.js

/* Handle Employee Related Routes */
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const Employee = require("../models/employee");

router.post("/add", (req, res, next) => {
  const newEmployee = new Employee({
    _id: new mongoose.Types.ObjectId(),
    name: req.body.name,
    age: req.body.age,
    profile_pic: req.body.profile_pic,
    designation: req.body.designation,
    organization: req.body.organization,
    date_of_join: req.body.date_of_join,
    experience: req.body.experience,
    skills: req.body.skills,
  });
  newEmployee
    .save()
    .then((result) => {
      console.log(result);
      if (result) {
        res.status(201).json({
          message: "Created Employee Successfully",
          employee: {
            name: result.name,
            age: result.age,
            profile_pic: result.profile_pic,
            designation: result.designation,
            organization: result.designation,
            date_of_join: result.date_of_join,
            experience: result.experience,
            skills: result.skills,
          },
        });
      } else {
        res.status(404).json({
          message: "No Valid Entry Found",
        });
      }
    })
    .catch((err) => {
      console.log(err);
      res.status(500).json({
        error: err,
      });
    });
});

module.exports = router;

Above we are just using the Router functionality provided by express. We also import the model for the Employee, because we need to tell mongo on what collection we are adding the data to.

In router.post we pass a request and response so that we can fetch the values we give in our body req.body and add it to our Employee model using the new keyword. Here you can see that skills we will directly take from body as an array. We don't need to do anything here specifically for many nested documents.

Now we need to add the routes to the index.js to tell express the route it needs to go to for this resource.

index.js

require("dotenv").config();
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const employeeRoute = require("./api/routes/employee");
const mongoose = require("mongoose");
const app = express();

mongoose.connect(
  `${process.env.MONGO_URL}`,
  {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  },
  function (err, client) {
    if (err) {
      console.log(err);
    }
    console.log("connected!!!");
  }
);

app.use(cors());
app.use(morgan("dev"));
app.use(express.json());
app.use("/api/employee", employeeRoute);
app.get("/", (req, res) => {
  res.status(200).json({
    message: "API is Working",
    routes: [{ method: "POST", endpoint: "/api/employee" }],
  });
});

app.listen(9000, () => {
  console.log("Express App Running http://localhost:9000");
});

We will use that resource using the app.use method provided by express. Now for testing let's go to postman and send a request and try it out.

When i send a POST request at http://localhost:9000/api/employee/add with the body like below

{
    "name": "Sid",
    "age": 30,
    "designation": "Dev",
    "organization": "ABC",
    "experience": "0",
    "skills": [{"name": "Javascript"}, {"name": "React"}]
}

I get back a response like this.

image.png

๐ŸŽŠ๐ŸŽŠ Yes it works ๐ŸŽŠ๐ŸŽŠ. You can also view the same data in the Mongo Atlas cloud as well. If you have your account open, go to the dashboard and you can see something like below

image.png

This is really good starting point for our api as we are able to create an employee, now we need to add the other routes also. But before that, we will take much more deeper dive into uploading images and using that as the profile picture.

I will be using Azure Blob Storage to upload my images and use that image url in the profile pic. You are free to use any storage service online. Once of the best choices is AWS S3 or Firebase these are more professionally used. But I wanted to just try out Azure. We will see that in the 3rd part of the series.

ย