How to Set Up a Node.js Server and MongoDB Database

Background to the Project ๐Ÿ”Ž

Having spend some time on my bootcamp working on JavaScript and React, we were given some time to explore our own pathway's based on what interested us the most. For me it made sense to start looking at the back-end, with a view to potentially building my first full stack site.

First I needed to decide which stack to focus on, and after a bit of research I settled on MERN (MongoDB, Express, React and Nodejs). This made the most sense as I already had experience of React.

The Project ๐Ÿ“…

The example used in this article refers to a lesson planning project that has similar functionality to a blog site. Once the main features are setup it could ba adapted for many purposes. The user will be able to complete a from with the details of their lesson, access the currently planned lessons to view, and update them.

Step One - Setting Up The Front End ๐Ÿšช

I am going to focus on the back end in this article, so I'm not going into detail about the React part of this project here.
The first step is to complete the front end - if using React you will need your components, state and router set up.

Step 2 - Setting Up A Server ๐Ÿ–ฅ๏ธ

Now out front end is set up, it's time to make our server using Node and Express. We will then create a series of HTTP endpoints to cover GET and POST requests. We'll use these to access the list of lessons, a specific lesson, and also to update a current lesson.

Node is an open source server environment that allows us to run JavaScript on the backend.

To initialise our backend, we need to create a new folder, in this case called backend, with an server.js folder inside (I placed this outside the front-end folder).

Once this is done, we will create a package.json file using the following command in the terminal:

$ npm init -y

We will then need to to isntall the following packages:

$ npm install express cors mongoose

express is a web framework for Node.js
cors provides an express middleware that helps us to enable cors with various options (here it will allow requests from our client domain to our server domain)
mongoose is a Node.js framework that allows us to access MongoDB (where we will create our database) in an object-oriented way.

The last package we will need to install is nodemon:

npm install -g nodemon

Each time we start running out server we will use the command nodemon server and this will mean that any changes we make will be taken into account as soon as they are saved. using install -g means that it is installed globally on our system.

Now we have all our dependencies installed it's time to set up our server in our server.js file. We will create an instance of the express server, require the cors middleware and set up PORT 4000 for the server to listen to:

const express = require('express');
const app = express();
const cors = require('cors');
const PORT = 4000;

app.use(cors());

app.listen(PORT, function() {
    console.log("Server is running on Port: " + PORT);
});

Running the server with nodemon server should now show the console log "Server is running on Port: 4000", and we know our server is up and running!

Step 3 - Setting up our MongoDB database with MongoDB Atlas ๐Ÿ—‚๏ธ

MongoDB is a cloud database and can be set up easily with a free account. This FreeCodeCamp tutorial gives an excellent overview on setting up the database.

Once our database is set up, we need to connect our database to our server. On the clusters page, click the connect button for your cluster and then select the "connect your application" option on the pop up menu. Copy the URI given as we will need it in our code.

To connect our database to our server we need the following code:

const dbURI =
  "**insert your URI from MongoDB here, remembering to replace the password and database info for your specific database**";

mongoose
  .connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => {
    app.listen(PORT);
    console.log("Server is running on Port: " + PORT);
  })
  .catch((err) => {
    console.log(err);
  });

If you can see both console logs then you know the database has been connected correctly!

Providing MongoDB with a Schema ๐Ÿ““

Before we start submitting data to our database, we need it to have a rough idea of what to expect first, these come in the form of Mongoose schemas.

In you backend folder, create a yourdata.model.js file. For example, my lesson planning app has the schema file lesson.model.js. The schema should outline the general form of the data, and what types of data are to be included. Here is my lesson schema:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

let Lesson = new Schema({
  lesson_name: {
    type: String,
  },
  lesson_date: {
    type: String,
  },
  lesson_time: {
    type: String,
  },
  lesson_details: {
    type: String,
  },
});

module.exports = mongoose.model("Lesson", Lesson);

Server Endpoints ๐Ÿ”š

Back in server.js, we now need to setup our server endpoints using express:

app.use("/lessons", lessonRoutes)

This means that the router will take control of all HTTP requests that start with the path /lessons. You will notice that res.json() or similar appears somewhere in each request. . This ensures our results are returned in json format.

We will be using the GET and POST methods here.

Route 1 - GET all items from the database:

lessonRoutes.route('/').get(function(req, res) {
    Lesson.find(function(err, lessons) {
        if (err) {
            console.log(err);
        } else {
            res.json(lessons);
        }
    });
});

Route 2 - GET single item from the database:

lessonRoutes.route('/:id').get(function(req, res) {
    let id = req.params.id;
    Lesson.findById(id, function(err, lesson) {
        res.json(lesson);
    });
});

Route 3 - POST a new item to the database:

lessonRoutes.route("/add").post(function (req, res) {
  let lesson = new Lesson(req.body);
  lesson
    .save()
    .then((lesson) => {
      res.status(200).json({ lesson: "lesson added successfully" });
    })
    .catch((err) => {
      res.status(400).send("adding new lesson failed");
    });
});

Route 4 - Update an existing lesson with POST:

lessonRoutes.route("/update/:id").post(function (req, res) {
  Lesson.findByIdAndUpdate(
    { _id: req.params.id },
    {
      lesson_name: req.body.lesson_name,
      lesson_date: req.body.lesson_date,
      lesson_time: req.body.lesson_time,
      lesson_details: req.body.lesson_details,
    },
    function (err, result) {
      if (err) {
        res.send(err);
      } else {
        res.send(result);
      }
    }
  );
});

This is slightly more indepth as it involves retreiving the id of the current lesson, then posting new values onto the schema.

At this stage a tool such as Postman could be used to check the GET and POST requests - we need these to be working properly before moving on.

Using Axios to Link the front end to the backend ๐Ÿ”—

Now it's time to connect the front end to the back end. The Axios library allows us to send our HTTP request from the front end to our chosen endpoint on the server. To install Axios, use the following command:

npm install axios

Now we are ready to write our requests into their components as necesssary. Use the following import statement at the top of the component:

import axios from "axios;

An axios GET request is made by calling axios.get(). The request takes in one parameter, - the URI for the corresponding endpoint.

Here are the GET requests used in the lesson planner:

axios
        .get("http://localhost:4000/lessons/" + id)
        .then((response) => {
          const lessonData = response.data;
          updateSpecificLesson(lessonData);
        })
        .catch(function (error) {
          console.log(error);
        });
axios
      .get("http://localhost:4000/lessons/")
      .then((response) => {
        const allData = response.data;
        updateLessonList(allData);
      })
      .catch(function (error) {
        console.log(error);
      });

An axios POST request is made by calling axios.post(). The request takes in two parameters - the URI for the corresponding endpoint, and the data to be passed to the database (object).

Here are the POST requests used in the lesson planner:

axios.post("http://localhost:4000/lessons/add", newLesson).then(
      (response) => {
        console.log(response);
        updateFormData(initialFormData);
        window.location = "/";
      },
      (error) => {
        console.log(error);
      }
    );
  };
axios.post("http://localhost:4000/lessons/add", newLesson).then(
      (response) => {
        console.log(response);
        updateFormData(initialFormData);
        window.location = "/";
      },
      (error) => {
        console.log(error);
      }
    );
  };

Resources Used ๐Ÿ“–

Code ๐Ÿ–ฑ๏ธ

The github repo for the final project can be found here

Final Thoughts ๐Ÿ’ญ

I hope to add more features to this project in the future, such as a more in-depth form to create a lesson, the ability to delete a lesson, and have a calendar view where the user can see the planned lessons. Keep your eyes peeled! ๐Ÿ‘€

If you got this far thank you for reading my first DEV article ๐ŸŽ‰

If you spot any errors or have any questions then please let me know in the comments!

9