Managing Complex Data Structures in NodeJS

Managing Complex Data Structures in NodeJS
Managing Complex Data Structures in NodeJS

Before talking about managing the complex data structures in NodeJS, Let’s first know what is NodeJS? And why do we use it?

node_js
Image Source: Simform

Introduction

According to Wikipedia, NodeJS (Node) is an open-source development platform for executing JavaScript code server-side. NodeJS runs single-threaded, non-blocking, asynchronously programming, which is very memory efficient.

This all seems to be very scary at first but don’t worry one thing you need to keep in mind for now is, it’s used for Backend and all is mostly JavaScript. It doesn’t mean that’s all but all other features you’ll get to know is alongside you will work more with NodeJS.

What you can do with NodeJS?

  • It helps you in creating dynamic page/content
  • You can do CRUD (Create, Read, Update and Delete) files on the server and database
  • It gives you an easy way to build scalable programmes

What is NodeJS File?

  • Node.js contains functions/programs that will be executed on certain events
  • A typical event is trying to access a port on the server
  • Node.js files must be started or initiated on a server before having any effect

How NodeJS works?

  • First, it sends the task/ or any request to the computer’s system
  • Ready to handle the next request
  • When you make any request and the file system has opened and read the file or executed the process then, the server returns the content to the client

For better understanding of managing complex data structures in NodeJS, Let’s make a Contact App where we will see all types of things like choosing database as MongoDB, how the requests are made, how queries work and how server works.

app_design

This is how our App will look finally and will work. As we can see in the above picture that for creating a contact list we would be needed the following details for the user:

  • Name
  • Contact
  • Email
  • Address

If we would have done something else suppose permanent address/ Residential address then we could also create it in the schema using ‘ref’. Don’t worry it all seems to be scary a bit but we would cover every aspect of our app. The very first thing in the mind while creating an app not specific for this contact app but generally should be, we should first think that what details we actually need to create our database schema.

Facebook Schema:

Suppose if I am Supposed to make Facebook then,

  • Sign-Up page

 I would be required the Name, Email, Password and Contact. These are very basic details for sign-up page or you can see for creating a User.

User Schema:

blog banner 1
const userSchema = new mongoose.Schema({
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true
    },
    name: {
        type: String,
        required: true
    },
 phone: {
        type: String,
        required: true
        //We can also add validation like phone number should be of 10 digits
    },
       });
  • Sign-In page
    Then on the Sign-in page, I will ask the user to enter his/her details as Email and password for authentication and in the backend will check if the user with those details exist or not. Right? Seems simple! Yes, it is don’t hustle that what will I do or how will I do, Just think what you actually need then process accordingly.
  • Defining Posts/Likes/Comment Schema

When implementing the post/ like /Comment schema then first need we would be required is that we will need to relate our post/like schema with the user for which we used ‘ref’ so we can establish a relation between our like/post schema and user schema because we know ultimately our like/post is related to the user that if I am posting any picture or liking someone else’s posts then with the help of this relation we’ll get to know which post is liked by which user or who is posting the image.

Post Schema:

const postSchema = new mongoose.Schema({
    content: {
        type: String,
        required: true
    },
    user: {
        type:  mongoose.Schema.Types.ObjectId,
        ref: 'User'

    },
    // include the array of ids of all comments in this post schema itself
    comments: [
        {
            type:  mongoose.Schema.Types.ObjectId,
            ref: 'Comment'
        }
    ],
    likes: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Like'
        }
    ]
    });

Contact App

Look here we have defined the schema and given it a reference to the comment /user /like with which we want to relate and type of the ‘object mongoose.Schema.Types.ObjectId’. But here our focus is to create the Contact App, we’ll talk about the Facebook App some other time but it would be fun for sure.

Before going further let’s understand the workflow of our app with the help of an image like which files will be present in which folder:

  • Assets: In this folder, we will store static files such as Images/ CSS/ JavaScript
  • Config: In this, we will store the mongoose.js file which will consist of the details of our MongoDB database which is basically the local connection
  • Models: In this, we are going to store the contact.js file which is basically the schema of our Contact Schema model
  • Node_modules: In this folder, all the dependencies or external libraries/package we install will be stored in it
  • Views: Here basically HTML code of our file goes into this
  • Index.js: Index.js is the main file responsible for the running of our local server and all the routes or link for any other page are directed from here
  • Package.json: It consists of the information of our dependencies/package installed
Image Source: Fettblog.eu

It’s a Meme but you must have understood that as node_modules contains all the dependencies of your app so don’t forget it to add in the .gitignore file before uploading it to the github.

  • Contact-Schema

Here is the ContactSchema for our App:

const mongoose= require('mongoose');    //we will require for so we can create mongoose model

const contactSchema= new mongoose.Schema({
    name:{
        type: String,
        required: true
    },
    phone: {
        type: String,
        required: true
        //We can also add validation like phone number should be of 10 digits
    },
    email:{
        type:String,
        required:true
    }
});

//now we have defined a variable where we will store this schema
const Contact = mongoose.model('Contact',contactSchema);

//now we can use this schema anywhere in the app with using this Contact app
module.exports= Contact;

But now we have defined our schema that what things will be stored but we are forgetting something isn’t it? Yes we are forgetting where will we store it till now we have only decided what we’ll store but not where we’ll store or what database we’ll choose. We will take MongoDB as database and for this we’ll make file mongoose.js file inside config folder for which you can refer the main image above for understanding the workflow of our app.

  • Mongoose
//Require the library
const mongoose= require('mongoose');

//Connecting to database
mongoose.connect('mongodb://localhost/contacts_list_db');

//acquire the connection to check if it is successfully connected to DB
const db= mongoose.connection;

//For printing error 
db.on('error',console.error.bind(console,'error connecting to db!'));

//For printing successful message
db.once('open',function(){
    console.log('Successfully connected to DB!');
});

module.exports=db;

Here our main file for the NodeJS would be index.js file which will contain all the details about our app. And our details for our html page will be written in Home.ejs file with the help of which we will render out html code. So let’s try to understand each thing one by one starting with index.js.

  • Index.js
const express=require('express');
const path=require('path'); 
const port=8000;

const db= require('./Config/mongoose');
const Contact= require('./models/contact'); //with this we can use our schema here which we created earlier

const app=express();

app.set('view engine','ejs');   
app.set('views',path.join(__dirname,'views'));      //it will join my current directory with folder name specified
app.use(express.urlencoded());             //Middleware which will encode the url which we pass
app.use(express.static('assets')); //Look for a static file to load which is in folder named assets e.g. css/images/js

On home.ejs file we will be required to make the form like this in which we will ask the user to fill all the details required:

  • Form-creating
<form action="/create-account" method="POST">
            <input type="text" name="name" placeholder="Enter Name">
            <input type="number" name="phone" placeholder="Enter Phone">
            <input type="email" name="email" placeholder="Enter email">
            <button type="submit">Add Contact</button>
        </form>

On the webpage we’ll get something like:

Look in the action of the form there is the link is given “/create-account” it means after filling all the details in the form when we will click submit button then it will take us to the URL specified in the action of the given form and also one more thing to keep in mind is here the method type is POST. In the backend there’s method defined what happens when the request if of type post:

  • Submit Action
app.post('/create-account',function(req,res){
    console.log(req.body);    //it will print all the details on NodeJS which we have filled in the form 

    //As we have imported the contact schema in a variable named Contact and in that schema we have name,phone and email
    Contact.create({        //it will take the details which we filled in the form and will fill in the schema
        name: req.body.name,
        phone: req.body.phone,
        email:req.body.email
    },function(err, newContact){    //if we're able to create Contact successfully we'll get details in the newContact variable
        if(err){
            console.log('error in creating contact!');
            return;
        }
        console.log('****',newContact);
        return res.redirect('back');
    });
});
Image Source: Medium

Let’s see if you get the meme or not?

Well you must have understood why I have to write console.log in the code mostly.

After we click the submit icon then our webpage reloads, it means it basically redirects us to the same page or should I say to the HOME page and in the backend what happens let’s see:

  • Homepage Action
 app.get('/',function(req,res){              //This is telling me about the home page
    //console.log(__dirname);           For printing the name of directory 
    //console.log('my name from req',req.myName);
    Contact.find({},function(err,contactList){ //here will find the contact in database and if found then store it in the variable named "contactList"
        if(err){
            console.log('Error in fetching contacts from db');
            return;
        }
        return res.render('home',{
            title: "Contacts List",
            contact_list: contactList
        });
    });

Okay So what we get to know from the above image that when the page reloads then it finds all the contacts present in the database and basically after fetching all contacts it will store the contacts in a variable named contactList then this variable is passed to the home page. Just see in the above image what we have written in the res.render is ‘home’ is the home page of our website i.e. home.ejs and int the title we are giving the title name and int the contact_list we are copying the contactList.

After that our web page should be able to display the contacts on the page right? Hm. Not yet! Because of that, we’ll have to write the code for printing the contact present in the variable named contact_list. Please note that all contacts fetched from the database were first in the contactList variable in the index.js file but there we render the home and passed all the contacts in the variable named contact_list.

In Home.ejs we will write the logic for printing the contact let’s see:

 <h1 id="page-heading">Contact List</h1>
        <div>
            <ul>
                <% for(let i of contact_list) { %>  <!--this will print the contacts like a loop as we used in the javascript-->
                    <div class="list">
                    <li>
                        <p><%= i.name %></p> <!--As the i here represents particular conatct present in the contact list then it will print all details associated with it-->
                        <p><%= i.phone %></p>
                        <p><%= i.email %></p>
                    </li>
                    <div style="margin-top: 30px;" class="delete-button">
                                <a href="/delete-contact/?id=<%= i._id %>">
                                <i class="fas fa-window-close"></i>
                        </a>
                    </div>
                </div>
                <% } %>
            </ul>
        </div>

Here on the front of every contact, We are also going to put a cross icon and make it a hyperlink. So when we click on it, it’ll take us to some URL that will ultimately fetch that particular contact with the help of the id of a contact and delete it. You must be thinking how will get the id? Right? Actually, If you’ll understand the above code then you’ll find when we are passing the href in the anchor tag for hyperlink then we’re also passing the id of the contact in it also.

So finally out page will look something like this when we click on submit button and all those request on server-side as well as on the front end gets handled best.

Now finally our App is almost over but with one functionality left that what will happen on server-side when will click the cross icon and it will take us to that URL specified in the <a> tag of the cross icon. Let’s understand:

  • Delete Action
app.get('/delete-contact/',function(req,res){
    console.log(req.params);
    let id=req.query.id;
    
    //Find the contact by id and delete it
    Contact.findByIdAndDelete(id,function(err,){
        if(err){
            console.log('can not delete');
            return;
        }
        return res.redirect('back');
    });
})

Frequently Asked Questions

What is use of module.exports in NodeJS?

For exporting that particular module so we can use it anywhere in the app.

What is package.json file?

It contains metadata information about the app in short, it contains the information of the dependencies installed.

Conclusion

After this request gets executed then it will reload the page or will take us to the home page for which we have already discussed the code above and Yes it’s as simple as that and Congratulations! You’re done with your Contact App. But if you’re not the kind of guy who doesn’t understand much from the written things or not a blog kind of guy then you want to visit Learn My first express appA list of contacts in Node.js for free | Coding Ninjas.

On this link, you’ll find a couple of videos more and to see them you will have to first start your trial for free and then you can learn ContactList from the scratch. Don’t worry if you stuck somewhere else we got your back, You can check the source code for the same in the Github link.

Hope you enjoyed making the contact App, We’ll meet soon with another amazing blog.

By Yogesh Kumar