Adding MongoDB to the RestAPI

Technically next part of Part-2 of Nodejs Rest API

Now is the time to add MongoDB to our project so that we can add, update and list the products.

When we talk about Mongo DB, we talk about Collections. Collections in MongoDB are similar to Tables in MySQL. Here we don’t talk about the relations. We will have a collection of products where all the products will be listed with their properties. Each product is an Object.

To start it in app, we will create Model (representing a collection) and Schema will define the structure of data objects (a single product in our case).

Schema of product is going to be something like:

{

         name: String, 

         category: String,

         price: Number,

         availability: Boolean

}

In collection, we have a series of objects and each object is automatically assigned an ID by MongoDB.

To interact with Database, we install Mongoose and add it to application. We already added it in the beginning as part of dependency. Check Part 1 for confirmation

 

Create new folder named as ‘models ‘ and within this folder, create a new file product.js

within this file, add mongoose and get its Schema object like following:

const  mongoose = require(‘mongoose’);

const Schema = mongoose.Schema;

(you may avoid this line and use mongoose.Schema instead of ‘new Schema’ while creating schema object in next line)

Now creating schema for the products

const productSchema = new Schema({
  name:{
    type: String,
    required: [true, ‘Please provide product name’]
  },
  category:{
    type: String,
    required: [true, ‘Please provide category name’]
  },
  price:{
    type: Number,
    required: [true, ‘Please provide product price’]
  },
  availability:{
    type: String,
    required: false
  }
});

Pass on this schema to create the Model and export it to be used in other parts of the app.

const Product = module.exports = mongoose.model(‘Product’, ProductSchema);

Next to it, we will define and export functions to get, set and update products. Before that, if you don’t already have MongoDB setup in your machine:

Install and run Mongod.exe in the background. This file lies in Bin of MongoDB installed directory.

After MongoDB is successfully installed and setup, start using it and connecting application to it, open Command Line / shell and start MongoDB service.

Browse to its bin like following on my windows machine:

C:\WINDOWS\system32>cd C:\mongodb\bin

C:\mongodb\bin>net start MongoDB
The MongoDB service is starting..
The MongoDB service was started successfully.

Now execute ‘mongo’ to start server like following and it showed warnings too(I chose to ignore them for now):

C:\mongodb\bin>mongo
MongoDB shell version v3.4.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.2
Server has startup warnings:
2017-04-04T14:46:13.509+0400 I CONTROL [main] ** WARNING: –rest is specified without –httpinterface,
2017-04-04T14:46:13.510+0400 I CONTROL [main] ** enabling http interface
2017-04-04T14:46:15.603+0400 I CONTROL [initandlisten]
2017-04-04T14:46:15.603+0400 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-04-04T14:46:15.603+0400 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2017-04-04T14:46:15.603+0400 I CONTROL [initandlisten]
>
> show dbs
admin 0.000GB
local 0.000GB
meanauth 0.000GB
mycustomers 0.000GB

 

Connect to MongoDB:

Got to app.js and add mongoose under express and body-parser:

const mongoose = require(‘mongoose’);

mongoose.connect(‘PATH_TO_COLLECTION’);

to get PATH_TO_COLLECTION, Create a folder named as config and create a file in that folder as database.js

Add following statement next to require statement of require mongoose:

const config = require(‘./config/database’);

replace PATH_TO_COLLECTION with config.databasepath.

write following in database.js

module.exports = {

databasepath: ‘mongodb://localhost:3340/productsapp’,

secret: ‘anysecretstring’

}

 

 

After connect, add following to app.js

mongoose.Promise = global.Promise;

mongoose.connection.on(‘connected’, () => {

    console.log(“Database connected”);

});

mongoose.connection.on(‘error’, (err) => {

     console.log(“error connecting DB’);

});

By this time, there is no existence of DB ‘productsdb’ or any collection in it called product.

Lets start populating things using post request and it will be automatically created.

In order to populate using ‘post’ request, go to /routes/api.js:

First include mongoose and ../config/database.js using following code

const product = require(‘../models/product’);

const router = express.Router();

Then use following code within routes.post block:

product.create(req.body).then(function(tmpProduct){
    res.send({“req”: “Post the information for the product”, “returnVal”: tmpProduct});
});

Above function creates an object in Products collection in the Database we connected. At this step, if DB was not available, it would be created automatically.

As we have used ‘Promise‘ while connecting to DB above, we will have to wait for the completion of record using ‘product.create‘ function and use keyword ‘then‘ that takes a function as a parameter. This parameter is the record just created.

As we don’t have any UI yet, you may use Postman to test this functionality.

Now, what if user sends a request with missing value of a compulsory field. As I missed ‘name’ in one request that is compulsory property for the collection objects as per schema we defined. I got following error:

(node:15444) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ValidationError: Please provide product name

Above error appeared in console of command line and crashed the app. So, for a real app, it requires error handling:

In routes/api.js file, where we added a create function call in POST request, add catch statement that will make the code look like:

product.create(req.body).then(function(tmpProduct){
  res.send({“req”: “Post the information for the product”, “returnVal”: tmpProduct});
}).catch(next);

In the app.js file, under app.use(routes), we will create a custom function to be used for error handling. Add following code there:

app.use((error, req, res, next) => {
  console.log(error);//this will help us understand what are the options to display it to user.
  res.send({errcode: 101, message: error.message});
});

I have also added bodyParser like following:

const bodyParser = require(‘body-parser’);

Now, use it just before using routes as we have to parse the request body before we use it for routing.

app.use(bodyParser.json());

Leave a Reply

Your email address will not be published. Required fields are marked *