cft

Learn How to Build a Restful CRUD API using NodeJS, Express, and MongoDB

Create a CRUD API using nodeJS and connect it to a MongoDB database using mongoose.


user

Remi Gathoni

2 years ago | 5 min read

Introduction

CRUD stands for Create(Insert data to database), Read (Retrieve data from database), Update (Edit data from database), and Delete (delete data from database)

It is a
popular design through which Web APIs interact with databases.

This tutorial shows you how to:

  • Set up an express server
  • Set up routes with express
  • Connect to MongoDB using Mongoose
  • Write mongoose models
  • Use Mongoose to make database queries

Prerequisites

  • At least node 8.10 and npm >= 5.6
  • Working knowledge of nodeJS
  • JavaScript concepts like arrow functions, object destructuring, and async/await.
I am using Ubuntu 18.04 and a VS Code editor

Create a new folder

Open your terminal and create a new folder and move into it.

mkdir crud-api-nodejs && cd crud-api-nodejs

Initialize npm. You can change the options or you can accept the default options.

npm init -y

Create an Express Server

Install Express

npm i express

Create server.js and open VS Code

touch server.js

code .

In ./app.js, add the following code

// Require express

const express = require('express')

// Initialize express

const app = express()

// parse json objects

app.use(express.json())

// parse url encoded objects- data sent through the url

app.use(urlencoded({ extended: true}))

// create a server

const PORT = 8080

app.listen(PORT, () => {

console.log(`Server running on port ${PORT }`)

}

In the above code, we have,

  • Added express to our app
  • Initialized express
  • Added options to parse JSON and URL encoded data.
  • Started a server

Connect to database

In ./db.js

const mongoose = require('mongoose')

const dbURI = 'mongodb://localhost:27017/bookDb'

mongoose.connect(dbURI, {useNewUrlParser:true})

// connect to database

const db = mongoose.connection

// if error

db.on("error", (err) => {

console.error(`err: ${err}`)

})// if connected

db.on('connected', (err, res) => {

console.log('Connected to database')

})

Import ./db.js to ./server.js

const express= require('express')const app = express()

const db = require('./db')

.

.

.

Create Book Schema Model in ./bookSchema.js

const mongoose = require('mongoose')const bookSchema = mongoose.Schema({

title: {

type: String,

required: true

},

author: {

type: String,

required: true

},

publisher: {

type: String,

required: true

},

read: {

type: Boolean,

required: true

}

})

// Export modelmodule.exports = mongoose.model('Book', bookSchema)

Create

Here is what happens

  • A client will send book info to our server through the request body.
  • Check whether the data was actually sent, if not, send a bad request response
  • Create a new record in the database
  • If successful, send a 201 created response back

Let's first create a helper function for creating a database record

In ./dbHelpers.js add the following:

const Book = require('./bookSchema')exports.create = async (data) => {

try{

const newBook = new Book(data) const savedBook = newBook.save()

if(!savedBook) throw New Error()

return {error: null}

} catch (error) {

return {error: error.message}

}

}

Remember to import the helper function in ./server.js

const { create } = require('./dbHelpers')

Now in ./server.js, add the following

app.post('/create', async (req, res) ⇒ {

//check if req.body is empty

if (!Object.keys(req.body).length) {

res.status(400).json({

message: ‘Request body cannot be empty’

})

}

const {title, author, publisher, read} = (req.body)

// create a record in db

const book = await create({title, author, publisher, read})

if (book.error) {

res.status(500).json({

message: book.error

})

}

res.status(201).json({

message: ‘New book record created’

})

})

READ

Read all

To read all book records in the database, create a query that matches all the documents.

In ./dbHelpers.js, add the following

exports.readAll = async () ⇒ {

try{

const books = await Book.find({})

if (!books) throw New Error()

return {error: null, data: books}

}catch(error) {

return {error: error.message, data: null)

}

}

Add route in ./server.js

. . .

const {create, readAll } = require('./dbHelpers')

. . .

app.get('/read-all', async (req, res) ⇒ {

const books = await readAll()

if (books.error) {

res.status(500).json({

message: error.message,

books: books.data

})

}

res.status(200).json({

message: ‘success’,

books: books.data

})

})

Read One

To retrieve one record, use,findById and pass the Id in the URL as a parameter.

Add a helper function in ./dbHelpers.js

exports.readOne = async (id) ⇒ {

try{

const book = await Book.findByIdAndUpdate(id)

if(!book) throw new Error()

return {error: null, data:book}

} catch (error) {

return {error: error.message, data:null}

}

}

Add route in ./server.js

. . .

const {create, readAll, readOne } = require('./dbHelpers')

. . .

app.get('/read-one/:bookID', async (req, res) ⇒ {

const book = await readOne(req.params.bookID)

if (book.error) {

res.status(500).json({

message: book.error,

books: book.data

})

}

res.status(200).json({

message: 'success',

book: book.data

})

})

UPDATE

Pass in the id of the document you want to update via the URL and the data to update via the request body.

In ./dbHelpers.js

exports.update = async (id, data) ⇒ {

try{

const updatedBook = await Book.findByIdAndUpdate(id, data,{new: true})

if(!updatedBook) throw new Error()

return {error: null, data: updatedBook}

} catch (error) {

return {error: error.message, data: null}

}

}

In ./server.js

. . .

const {create, readAll, readOne, update } = require('./dbHelpers')

. . .

app.put('/update/:bookID', async (req, res) ⇒ {

if (!Object.keys(req.body).length) {

res.status(400).json({

message: ‘Request body cannot be empty’,

book: null

})

}

const book = await update(req.params.bookID, req.body)

if (book.error) {

res.status(500).json({

message: book.error,

book: book.data

})

}

res.status(200).json({

message: ‘success’,

book: book.data

})

})

DELETE

Delete One

Pass the Id of the document to delete via the URL.

In ./dbHelpers.js

exports.deleteOne = async (id) ⇒ {

try{

const isDeleted = await Book.findByIdAndDelete(id)

if (!isDeleted) throw new Error('')

return { error: null}

}catch (error) {

return { error: error.message}

}

}

In ./server.js

. . .

const {create, readAll, readOne, update, deleteOne } = require('./dbHelpers')

. . .

app.delete('/delete/:bookID', async (req, res) ⇒ {

const isDeleted = await deleteOne(req.params.bookID)

if (isDeleted.error) {

res.status(500).json({

message: isDeleted.error,

})

}

res.status(200).json({

message: 'Deleted Successfully)

})

})

Delete All

In ./dbHelpers.js

exports.deleteAll = async () ⇒ {

try{

const isDeleted = await Book.deleteMany({})

if (!isDeleted) throw new Error('')

return {error: null}

}catch (error) {

return { error: error.message }

}

}

In ./server.js

. . .

const {create, readAll, readOne, update, deleteOne, deleteAll } = require('./dbHelpers')

. . .

app.delete('/delete-all', async (req, res) ⇒ {

const isDeleted = await deleteAll(req)

if (isDeleted.error) {

res.status(500).json({

message: isDeleted.error,

})

}

res.status(200).json({

message: 'Deleted Successfully)

})

})

And that's it a simple CRUD API using mongoose, express, and nodeJS.

I learned a lot when writing this post and I hope you learn something too.

If there is anything in this post that is not clear please let me know in the comments.

Thanks for reading and Happy coding ☺️

Upvote


user
Created by

Remi Gathoni

Software developer. Technical Writer . NodeJS/MongoDB/ReactJS


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles