DEV Community

AdewoleCode
AdewoleCode

Posted on

How to build a RESTful crud API with ExpressJS and mongoDB Database for newbies

in this tutorial, i am going to be be listing a step by step guide and explanations on how to create a restFUL crud API with ExpressJS and MongoDB database.

first of all, what is an API? API is an acronym for Application Programming Interface. I like to think about an API as the layer between the frontend and the backend part of our app, a link where information is being exchanged between the browser and the server

REST(representational site transfer) is basically an architecture for how an API should be structured(a set of guidelines
for how the browser should send resources to the server) e.g using HTTPS, using cachable data that streamlines interactions. in summary, REST is a set of guidelines for creating APIs which makes web applications faster and more lightweight,
with increased scalability.

so a restFUL API is basically an application programming interface that adheres to the constraint of a REST architecture to exchange information between the browser and server(frontend and backend).

Now that we understand what a RESTful API means, let's look at how we create one in ExpressJS.

Step 1: we create the express application

  • create a new folder named "ExpressJS API".

  • open the folder with your visual studio code application.

  • open the integrated terminal in your visual studio code and run "NPM init -y". that command will create a package.JSON file( a file that keeps track of borrowed code from the NPM library that we will be using to build our application)

  • next, we install some borrowed code from NPM(dependencies) to help jump-start our application. In the terminal we run "NPM install expressJS body-parser mongoose --save" and what that will do is, install the 3 dependencies we need to fire up our application. the expressJS package creates our express library that gives us access to some cool functions that makes whipping up our server way easier, body-parser is a middleware that parses incoming requests(gives us access to the request object from the browser in a way that makes it readable on our application, the mongoose package is to communicate with our mongoDB database(a database that stores our application data)

Step 2: setting up the web server to listen and respond to request from the browser

  • create a new JavaScript file inside the "expressJS API" folder, named "server.JS"

  • in the new server.JS file, import the express package(one of the borrowed code) we installed earlier, into the new JavaScript file and create an instance of it. your code should look something like
    const express = require("express") then we instantiate the express instance we created and store in a new variable named "app". see example const app = express()

  • next, we add the body-parser middleware to our application by adding it to our server.JS setup, by using a method provided to us by express. the use method. this is a method we use to pass in a middleware to our ExpressJS application. we create an instance of the body parser object and then pass it to our use method as a middleware, const bodyParser = require("body-parser)
    app.use(bodyParser.urlencoded({extended: true})
    app.use(bodyParser.JSON()

  • after we setup our express and body parser instances, next we define a simple GET method by calling the get method on the variable that's holding our instantiated object. the get method takes 2 argument, the route and a callback function that triggers every time our route gets a request. the callback function takes 2 arguments, "req" and "res", each representing the request and the response object respectively. and we can use the get object the callback is giving us access to, exchange data with the browser.
    we then use the request object to send a simple message to the browser every time it hits our route.

example app.get('/', (req, res)=> {
res.send('server is running')
})

. we call the GET method on the express instance we created earlier, the get function takes 2 arguments, a path(route) and a
call-back funtion that triggers everytime our route gets a request. we use the res object to return a simple message "server running".

example app.get('/', (req, res) => res.json{"msg": server is running"})

  • we create a port( a port represents a place where our browser and server connects) eg const port = 5050

  • listen on that port for incoming requests by using another method made available to us by express, a "LISTEN" method on instance we created. the listen method. the listen method takes
    2 arguments which is, the port we set up,
    and a call back function that we can use to write something to the console. example app.listen(PORT, ()=> {console.log(server is running on ${port}}

  • finally, we open the integrated VScode terminal, and run
    node server.js, then navigate to localhost:5050(port) on your web browser, and you should "server running.

...and congrats, you just created a web server with ExpressJS

Step 3: Connecting our ExpressJS application to mongoDB database.

remember we installed a mongoose dependency from NPM? we use that package to communicate with our
mongoDB database(I'm assuming you have created one already, if not, search mongoDB on google and follow process on how to create account).

  • still In our server.JS file, below the express instance and the body parser, create a new instance of the mongoose object(remember how we created the express instance earlier on?), we require
    the object and store in a new variable named "mongoose"

  • on the mongoose instance we created, we call a "connect" method(provided to us by the mongoose library) and pass in a connection string we get from mongoDB(you should have one if you created a mongoDB account and data clusters), since it's an asynchronous function it's better we wrap it in a tryCatch. so that we can spit back the error if there is one.
    example const start = async () => {
    try {
    await connectDB(process.env.MONGO_URI)
    console.log('connected');
    app.listen(port, () =>
    console.log('Server is listening on port ${port}...')
    );
    } catch (error) {
    console.log(error);
    }
    };
    start();

note: it is good practice to setup your MONGO_URL connection strings in a dotenv file and reference it like i did in my code. since you'll be pushing your code to GitHub or a public code sharing platform, it's not very smart to leave your connection naked for everyone to see. they could use it to mess with your database.

sweet. our application is connected to the mongoDB database.

Step 4: We create a mongoose model.

A mongoose model is a wrapper on the mongoose schema.

A mongoose schema on the other hand is basically the structure of our document. like a skeleton of how we want our data to be stored in the mongoDB database( yes, we get to create the structure of how our data should be stored on the database), MongoDB gives us that flexibility(cool, right?).

to setup our mongoose model, we need to

  • create a new file on the root level of our folder named "model" and as the name suggests, any mongoose model we create goes in there.

  • inside the model folder, we create a new file called "appModel.js", in that file, we create a mongoose instance, and save in a new variable. on that variable, we call a method named "Schema" with a capital "S" to create a schema(remember?, skeletal structure of how we want our document to look in the mongoDB database). the schema Method takes an object and in the object, we create properties as exactly as we want them stored in our Database.

  • finally, export mongoose model we created to get access to it in other files.

e.g const AppSchema = mongoose.Schema(
{
username: {
type: String
},
message: {
type: String,
},
module.exports = mongoose.model("App", AppSchema)

Step 5: Define other routes that performs rest of our crud operations.

we created a get route in the server.js file, when we created the server earlier on. where we returned a "server is running" with the response object.
remember:this is a getmessage route that handles a get request app.get('/getmessage', (req, res) => res.json{"msg": server is running"})

now, back in the server.js file, we want to create other routes for our crud functionalities

setting up other routes

  • a createMessage route that handles post request to our route. we also get access to the request and response object. app.post('/createMessage', (req, res) => res.json{"msg": server is running"})

  • a "/updatemessage" route that handles update request to our route: app.post('/updatemessage', (req, res) => res.json{"msg": server is running"})

  • a "/deletemessage" route that handles delete request to our route: app.post('/deletemessage', (req, res) => res.json{"msg": server is running"})

we setup 4 routes(getmessage route, createMesage route, updatemessage route and a deletemessage route).
next, we create controller functions( the callback functions that get triggered when any of the routes we set up gets
a request.

Step 6: Create Controller Functions

  • create a new folder inside the ExpressJS API folder named "controllers".

  • create a file in the controllers folder named appController.js

  • inside the appcontroller.Js file, we import the mongoose model we created, the APP model(hope you didn't forget about it yet?), the one that has the "message and name" as properties on it. we store in a new variable "appMessage"

  • we then use the appMessage variable that holds our mongoose model to construct the controller functions.
    so we create a new asynchronous funtion getMessage, we have access to the req and res since we'll be using this functions as a callback function we pass next to the routes we setup in server.js

  • mongoose gives us a couple of method we can use to query our database, which makes performing our crud functionalities easier

  • create message functionality.
    e.g const messageModel = require(//"path of model")
    const createMesage= async (req, res) => {
    const message = await messageModel.create({"name", "message") _our model takes 2 properties_
    res.json({message})

    we created an async function, created a message based on the model with the "create" method we got from mongoose, and used the response object to send a reply to the browser. we could also extract data from on the request body and use it to create our message.

  • get message functionality.
    e.g const messageModel = require(//"path of model")
    const getMesage= async (req, res) => {
    const message = await messageModel.find({name: "ade"})
    res.json({message})

here, we basically call a "findOne" on the model and pass in "name" and that should get all messages in our database, with that particular name property we passed in as a property

  • update message functionality. e.g const messageModel = require(//"path of model") const updateMesage= async (req, res) => { {name} = req.body const message = await messageModel.findOne({name: "ade"}) message.name = newName res.json({newName})

we get a new name from the body of the request object(req.body), extracted it, find the user with the name of "ade" and basically set the name property to what we get from the browser, we then send the send the update name back as response.

  • delete message functionality e.g const messageModel = require(//"path of model") const deleteMesage= async (req, res) => { const message = await messageModel.findOneandDelete({name: "ade"}) res.json({"message deleted})

we are using the "findOneAndDelete" method from mongoose to delete the message property with the name of ade. and using the response object to send back a response.

these are just a few examples, they could be get more elaborate and complex than the few basic examples i created here.

Step 7: Connect our controller functions to our routes

after we created the controller functions and the routes. we connect them by importing the controller functions into the server.JS and setting them as a second arguments after the routes.

example app.post('/createmessage', createMessage)
app.get('/getmessage', getMessage)
app.patch('/updateMessage', updateMessage)
app.delete('/deletemessage', deleteMessage)

so we have a route and it's corresponding controller functions that fires when any of the routes gets a request that's part of what our setup handles.

Ended up being a long write up but i had fun writing it, i hope you learnt a thing or 2. feed-backs are always welcomed if you found the article helpful.

Top comments (1)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Hi. If you would like to know how to correctly write REST URL's, follow this link. In REST, we don't do things like /deletemessage. Instead, we do HTTP DELETE http://server:port/messages/123. REST defines URI's for resources, and /deletemessage is not a unique message URI.