Build a school management from scratch using MongoDB & Express

Primerose Katena
10 min readAug 28, 2020

--

Introduction

MongoDB, Express and Nodejs are often used with familiar powerful frontend frameworks such as Angular or React to make an open source software development stack (or technology) for modern Javascript developers. These stacks are called MEAN and MERN respectively. Node.js is a cross-platform JavaScript runtime environment for executing Javascript code outside the browser (mostly on the server-side). There are a few frameworks developed to simplify creating Node.js apps. One of the them is Express.js.

Express is a Node.js web application framework that supports both web and mobile applications with numerous features such as handling requests and responses from multiple routes and port settings and connections. MongoDB is a NoSQL database that make use of collections and documents to store data. This article offers a hands-on tutorial for learning the basics of MongoDB, Express and Nodejs technologies and using the knowledge to build the backend of a web application from scratch.

Prerequisite:

  1. Fundamental knowledge of MongoDB database is crucial. You can use the online version or download the MongoDB Compass Community on your machine. I am using MongoDB Compass Community on my machine for this tutorial.
  2. Fundamental knowledge of Express is required.
  3. Fundamental knowledge of Node.js is also required. If you do not have Node.js installed on your machine, download the recommended version here.

Details of the project

We will build a student class registration app. This application allows us to create, view, update, and delete a class and students. We will use MongoDB for our database and Node.js and Express.js to build the backend of our web application.

The setup

We begin by creating a root folder called studentClass, where we will keep our project. Inside the studentClass, create a sub folder called backend.

The Nodejs setup

Open Command Prompt (CMD) or your preferred terminal. Navigate to the backend folder and generate the package.json file by issuing the npm init -y command. Once we get this, add node modules into the project by typing `npm install Node ` on the command line.

The Express Setup

Once we install Node.js, we need to install Express.js using this command: npm install express

The Nodemon

We do not always want to manually restart the server anytime we save new changes to our code. To automate the process install:

npm install nodemon -g

Once we add Nodemon, go back to the package.json, under scripts replace test with the following:

"scripts": {

"start": "nodemon app.js"

}

Starting with Nodejs and Express

Now let’s create a file called app.js in the backend folder and add the code below.

const express = require('express')

const app = express()

app.listen(3000, () => console.log("Listening on port 3000"))

Run `npm start` to start the server. You should see the below output indicating that our server is running on port 3000.

Listening on port 3000

The Database

For this tutorial, we will use MongoDB as our database. Specifically, we will use Mongoose, an Object Data Modelling (ODM) which helps us work with schemas easily. Any Mongoose model will be mapped to a MongoDB document.

To begin, install Mongoose as follows:

npm install mongoose — save

So far, we have installed the required server-side libraries needed for our project. Let’s start working on the database. In the backend folder, create a new folder called db. Inside db, create a folder called dbmodel.

Connecting to db

We will create our database using the MongoDB Compass Community which can be downloaded here. Open your MongoDB compass Community and click on the connect button:

The next step is creating a database by clicking on the create database button as shown below:

Add the database name and the collection name as shown below:

After successfully creating the database, it will be displayed on the list of databases you have. Navigate to that database and add another collection called students as shown below:

Our database is now complete! Let’s add a file called mongoose.js in the dbmodel sub folder to define how to establish a connection to the Compass database server.

//configure database

const mongoose = require('mongoose')

mongoose.Promise = global.Promise

mongoose.connect('mongodb://127.0.0.1:27017/myclasses', {useNewUrlParser : true, useFindAndModify: false})

.then(() => console.log("Database connected"))

.catch((error) => console.log(error))

module.exports = mongoose

Because our database is local, we used the URL below to connect to our database. As you can see the URL (localhost) has our database name myclasses :

'mongodb://127.0.0.1:27017/myclasses'

To connect to our database, import the mongoose.js file in the app.js file as shown below:

const mongoose = require('./db/mongoose')

As you can see below, we have been successful at establishing a connection to the local database server created in MongoDB Compass Community:

We then proceed to defining our schemas. Schemas represent the database logical view and has all the data constraints rules. A student class schema has two attributes: name and number of students in a class. In the dbmodel folder, create a file called class.js , where we will create a student class schema.

const mongoose = require('mongoose')

//S3 creating the Schema

const ClasssSchema = new mongoose.Schema({

name:{

type : String,

trim: true,

minlength: 3

},

numberOfStudents:{

type : Number,

trim: true,

minlength: 3

}

})

const Classs = mongoose.model('Classs', ClasssSchema)

module.exports = Classs

We also need to create a student schema in the dbmodel folder called student.js and add the following code.

const mongoose = require('mongoose')

//creating the Schema that enforce constraints on our database

const StudentSchema = new mongoose.Schema({

name:{

type : String,

trim: true,

minlength: 3

},

lastName:{

type : String,

trim: true

},

_classId:{

type: mongoose.Types.ObjectId,

required: true

}

})

const Student = mongoose.model('Student', StudentSchema)

module.exports = Student

We will now import the two schemas to app.js To securely allow our application to access resources from other origins, we shall use Cross-origin resource sharing (CORS) . Let’s import the schemas and configure our app to use CORS.

const express = require('express')

const app = express()

const mongoose = require('./db/mongoose')

const myclass = require('./db/dbmodels/myclass')

const student = require('./db/dbmodels/student')

//enable our app to parse json data format

app.use(express.json())

app.use((req, res, next) =>{

res.header("Access-Control-Allow-origin", "*")

res.header("Access-Control-Allow-Methods", "GET, POST, HEAD,

OPTIONS, PUT, PATCH, DELETE")

res.header("Access-Control-Allow-Headers", "Origin",

"X-Requested-With", "Content-Type", "Accept")

next()

})

app.listen(3000, () => console.log("Listening on port 3000"))

The post method

In a real world, students are enrolled into classes each academic year. That said, we should be able to create a class and register a student into our database. The code below creates a new class with details from the request body.

//posts method for creating a new student class

app.post('/myclass', (req, res) => {

(new myclass({'className': req.body.className, 'numberOfStudents' : req.body.numberOfStudents}))

.save()

.then((myclass) => res.send(myclass))

.catch((error) => console.log(error))

})

I will use insomnia app to test my APIs, feel free to use any other application like POSTMAN for the same purpose. I will create a main folder called myclasses in the insomnia app. In myclasses folder, I will create two folders, myclass and students.

Under myclass folder, I will add the new requests for testing all the APIs routes: creating, viewing, updating and deleting a student class. The snippet below makes a POST request to the API above, mainly for creating a new student class:

We successfully created the new student class. This class has a capacity of 200 students and it is called class of 2020. Each class should contain students. Our next step is writing code to registering students to a particular class. Add the code below in app.js:

// register a student into a class

app.post('/myclass/:myclassId/students', (req, res) =>{

(new student ({ 'name': req.body.name, 'lastName': req.body.lastName, '_classId' : req.params.myclassId }))

.save()

.then((student) => res.send(student))

.catch((error) => console.log(error))

})

The snippet below shows the input and output for testing the API for inserting a student in one of the classes we created. Take note of the class _id from the previous POST API.

Get

We also want to be able to retrieve all the classes we created from the database. Let’s create an API for viewing all student classes we have:

//read all classes

app.get('/myclass', (req, res) =>{

myclass.find({})

.then(myclass =>res.send(myclass))

.catch((error) => console.log(error))

})

Using the get method, we retrieve all the student classes as follows:

There are instances where it is important to retrieve a single class using its unique identification number. The code below allows us to do so:

//get one student class

app.get('/myclass/:myclassId', (req, res) =>{

myclass.findOne( { _id: req.params.myclassId })

.then(myclass =>res.send(myclass))

.catch((error) => console.log(error))

})

We would like to retrieve class of 2050 using its identification number. The snippet below shows the results:

We have added a number of students in different classes. Let’s write code that retrieve students that belongs to a certain student class using the class id:

//get all students from this classId

app.get('/myclass/:myclassId/students', (req, res) =>{

student.find({ _classId: req.params.myclassId })

.then((student) => res.send(student))

.catch((error) => console.log(error))

})

As shown below, we retrieved all the students that belonged to a specific class.

We, additionally, want to retrieve a single student from any class of our choice that belong to a specified class. To do that, we need to know their classId and studentId. Below is the code to do so.

//get one student

app.get('/myclass/:myclassId/students/:studentId', (req, res) =>{

student.findOne({ _classId: req.params.myclassId, _id: req.params.studentId })

.then((onestudent) => res.send(onestudent))

.catch((error) => console.log(error))

})

Once we save this, let’s test the API for retrieving one student from the database:

There are instances where you need to modify the student class information. One particular instance is when you want to rename a class or change the details of a student. The code below helps us to update information of any student class:

//update student class

//$set: req.body for auto update of values in the body

app.patch('/myclass/:myclassId', (req, res) =>{

myclass.findOneAndUpdate({ '_id' : req.params.myclassId }, {$set: req.body})

.then((myclass) => res.send(myclass))

.catch((error) => console.log(error))

})

Now let’s retrieve class of 2060 from our database using the id associated to it.

We noticed that class of 2060 (C2060) as created in the previous example was suppose to be saved as class of 2012. Using the insomnia app, let’s test the API for updating this information:

We successfully updated the student class information from C2060 to C2012, however, one student in class of C2012 called John Snow was mistakenly named John Morise. Here is the code that help us update any student information:

//update student information

app.patch('/myclass/:myclassId/students/:studentId', (req, res) => {

student.findOneAndUpdate({ '_id': req.params.myclassId, _id: req.params.studentId }, { $set: req.body })

.then((student) => res.send(student))

.catch((error) => console.log(error))

})

The snippet below shows the wrong details of John Snow as saved in our database:

We can now see the updated information about John Snow from the snippet below.

Deleting

It would be great to be able to delete student classes when we no longer need them. Here is the code for deleting a student class:

app.delete('/myclass/:myclassId', (req, res) =>{

const deleteStudents = (myclass) =>{

student.deleteMany({ '_id': req.params.myclassId})

.then(() => myclass)

.catch((error) => console.log(error))

}

myclass.findByIdAndDelete( { '_id': req.params.myclassId})

.then((myclass) => res.send(deleteStudents(myclass)))

.catch((error) => console.log(error))

})

The snippet below is the results for deleting a class in Insomnia.

Delete student

John Snow decided to drop out of the class to pursue his dream career (joining the movie industry). Below is the code for deleting any student from any class:

//delete student info

app.delete('/myclass/:myclassId/students/:studentId', (req, res) => {

student.findOneAndDelete({ _id: req.params.studentId, _classId: req.params.myclassId }).then((student) => res.send(student))

.catch((error) => console.log(error))

})

Let’s test the API for deleting a student:

We successfully deleted the student.

Conclusion

Congratulations, you successfully created a school application that keeps records of each class details and students enrolled in those classes. We tested out all our APIs using Insomnia application, and we got successful output. As you can see, MongoDB, Node.js and Express.js are a powerful combination for writing the backend logic for modern web applications.

--

--

Primerose Katena

Project Manager || Product Manager || Product Operations and Strategy|| Email: katenaprimerose@gmail.com