DEV Community

Cover image for Day 5 - Your first week in NodeJS
Gurpreet Singh
Gurpreet Singh

Posted on • Originally published at gsin.in

Day 5 - Your first week in NodeJS

Quick recap

In my previous article, I explained how to implement a template engine to get dynamic variables into your HTML file.

We used static data to show and save users in memory. In this article, we will now connect our application to MongoDB for better features and sustainability.

What is NoSQL

Big data changed how we used to think of databases and storage, we used to have relational databases like MYSQL, SQLServer, etc. but now we have another technique to store data called NoSQL.

It stores data in documents in the form of JSON, instead of tables with rows and columns and it works very well with JavaScript (Node.js). This is how data looks like in the MongoDB database.

[
  {
    "_id": "610ec10c78f7665bfa2cbf11",
    "age": 28,
    "name": "Bobbi Cannon",
    "email": "bobbicannon@dragbot.com"
  }
]
Enter fullscreen mode Exit fullscreen mode

When we are not sure about the data structure or what kind of data is expected we can blindly choose the NoSQL approach and the industry-leading option is to go with MongoDB.

MongoDB Integration

We will be using MongoLabs for our MongoDB database setup which comes with the free tier option.

You can go to https://account.mongodb.com/account/login and claim your free account. You can follow the given steps to create a new database.

Create a new project:
create-project

Save project with members (default is logged-in user)
save-project

Create your first database
create-db

Select free plan
select-plan

Once you create your cluster, it will take some time for the initial deployment.

Now you need to create a user for your database:
create-db-user

MongoDB Integration

Once you have your database and username/password created, we need to install the mongoose npm package on our local. $ npm install mongoose

To save your MongoDB details, you need to have a file with the name .env, which allows you to send these values in process.env or Node.js environment variables.

MONGO_HOST=my_hostname
MONGO_PASS=my_password
MONGO_USER=my_username
MONGO_DB=my_db_name
Enter fullscreen mode Exit fullscreen mode

You will get above information in MongoDB connect option like mongodb+srv://my_username:my_password@my_hostname/my_db_name?retryWrites=true&w=majority

After creating the .env file you need to install a couple of packages, please refer to the package.json file below:

{
  "name": "node",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "dotenv": "^10.0.0",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "mongoose": "^5.13.5",
    "nodemon": "^2.0.12"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we are ready to change our app.js file with MongoDB changes.

First, you need to require the dotenv package to get MongoDB credentials from .env or process.env.

require("dotenv").config();
Enter fullscreen mode Exit fullscreen mode

After requiring the package you will get access to all environment variables like this:
const { MONGO_USER, MONGO_HOST, MONGO_PASS, MONGO_DB } = process.env;

Now we will connect the application with MongoDB, it requires the below steps:

require("dotenv").config();
const mongoose = require("mongoose");

// connect to the database
async function connectDB() {
  const { MONGO_USER, MONGO_HOST, MONGO_PASS, MONGO_DB } = process.env;
  await mongoose.connect(
    `mongodb+srv://${MONGO_USER}:${MONGO_PASS}@${MONGO_HOST}/${MONGO_DB}`,
    {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useFindAndModify: false,
      useCreateIndex: true,
    }
  );
}

connectDB();
Enter fullscreen mode Exit fullscreen mode

We need to require the mongoose package, and then followed by mongoose.connect() we will connect our current to our MongoDB instance.

It's an async operation, you can use promise or async/await functions.

Once you are done with the connection, we will define our Schema and Modal.

Schema is required to let MongoDB know what kind of collections you are going to store into documents.

// Create Schema for users
const usersSchema = new mongoose.Schema({
  age: Number,
  name: String,
  email: String,
});

// Create Modal for users
const UsersModal = new mongoose.model("users", usersSchema);
Enter fullscreen mode Exit fullscreen mode

As I explained in my previous article, _id will be autogenerated by MongoDB.

Please refer to the following updated app.js file (reset of the project setup will remain the same):

require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();

// connect to the database
async function connectDB() {
  const { MONGO_USER, MONGO_HOST, MONGO_PASS, MONGO_DB } = process.env;
  await mongoose.connect(
    `mongodb+srv://${MONGO_USER}:${MONGO_PASS}@${MONGO_HOST}/${MONGO_DB}`,
    {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useFindAndModify: false,
      useCreateIndex: true,
    }
  );
}

connectDB();

// Create Schema for users
const usersSchema = new mongoose.Schema({
  age: Number,
  name: String,
  email: String,
});

// Create Modal for users
const UsersModal = new mongoose.model("users", usersSchema);

app.set("view engine", "ejs");

app.use((req, res, next) => {
  res.append("Access-Control-Allow-Origin", ["*"]);
  res.append("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
  res.append("Access-Control-Allow-Headers", "Content-Type");
  if (req.url.includes("/api")) {
    res.append("Content-Type", "text/json");
  }
  next();
});

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use("/assets", express.static("assets"));

const getUserInfo = (id) => {
  return USER_DATA.filter((obj) => obj._id === id);
};

// Get list of users, and set data
app.get("/", (req, res) => {
  UsersModal.find({}, function (err, docs) {
    if (err) {
      res.status(500).send(err);
    }
    res.render("index", {
      data: docs,
    });
  });
});

// Get single user by id, and set data
app.get("/user/:id", (req, res) => {
  UsersModal.findOne({ _id: req.params.id }, function (err, doc) {
    if (err) {
      res.status(500).send(err);
    }
    res.render("user", {
      data: doc,
    });
  });
});

// Loading view of contact page
app.get("/contact", (req, res) => {
  res.sendFile(`${__dirname}/contact.html`);
});

// RESTFul API Services

// get all users
app.get("/api/users", (req, res) => {
  UsersModal.find({}, function (err, docs) {
    if (err) {
      res.status(500).send(err);
    }
    res.send(docs);
  });
});

// get single user by id
app.get("/api/user/:id", (req, res) => {
  UsersModal.findOne({ _id: req.params.id }, function (err, doc) {
    if (err) {
      res.status(500).send(err);
    }
    res.send(doc);
  });
});

// delete single user by id
app.delete("/api/user/:id", (req, res) => {
  UsersModal.findOneAndDelete({ _id: req.params.id }, function (err, doc) {
    if (err) {
      res.status(500).send(err);
    }
    res.send(doc);
  });
});

// update single user by id
app.put("/api/user/:id", (req, res) => {
  const { name, age, email } = req.body;
  if (req.params.id) {
    UsersModal.updateOne(
      { _id: req.params.id },
      { name, age, email },
      function (err, doc) {
        if (err) {
          res.status(500).send(err);
        }
        res.send(doc);
      }
    );
  } else {
    res.status(500).send("id is missing in params");
  }
});

// add new user
app.post("/api/user", (req, res) => {
  const { name, age, email } = req.body;

  if (name && age && email) {
    UsersModal.create(
      {
        age,
        name,
        email,
      },
      function (err, doc) {
        if (err) {
          res.status(500).send(err);
        }
        res.send(doc);
      }
    );
  } else {
    res.status(500).send("error, user not added.");
  }
});

app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

Useful Links

Discussion (2)

Collapse
tayfunakgc profile image
Tayfun Akgüç • Edited on

Perfect article series for beginners. I would like to mention that express has built-in middleware for parsing request body. You don't need to use body-parser. You can use app.use(express.json())

Collapse
gsin11 profile image
Gurpreet Singh Author

Really helpful, thanks for mentioning it @tayfunakgc !