Introduction
In this blog post, I'll share my experience building a simple bookstore application using the MERN stack (MongoDB, Express, React, Node.js). I'll focus on setting up CRUD (Create, Read, Update, Delete) operations with Express Router and testing them with Postman. This project helped me understand how to structure a backend with Express and connect it to a MongoDB database.
Setting Up the Backend
Creating the Express Server
To start, I set up an Express server and only Listen to Client side requests when connection with the MongoDB atlas is Established Succesfully, Here is the code snippet for initializing the server:
import express from "express";
import { PORT, dbUrl } from "./config.js";
import { router as bookRouter } from "./routes/booksRouter.js";
import mongoose from "mongoose";
import Book from "./models/Book.js";
import cors from "cors";
const app = express();
app.use(express.json());
app.use(cors());
app.use("/books", bookRouter);
//listen to client Requests only after the Database connection is Success.
mongoose
.connect(dbUrl)
.then((result) => {
app.listen(
PORT,
console.log("connected to Atlas & Listening on PORT", PORT)
);
})
.catch((err) => console.log("Connection to Atlas Error", err));
Creating Schema and Model
In Mongoose, a schema defines the structure of the documents within a collection, specifying the types of data that each field can contain. A model is a wrapper for the schema that provides an interface to interact with the database, below is the code how i created Schema and Model using Mongoose.
import mongoose from "mongoose";
const bookSchema = mongoose.Schema(
{
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
publishedYear: {
type: String,
required: true,
},
},
{ timestamps: true }
);
const Book = mongoose.model("Book", bookSchema);
export default Book;
Setting Up API Endpoints with Express Router
Modularizing with Express Routers for Endpoint /books
to keep the code clean and organized.
//index.js
app.use("/books", bookRouter);
//bookRouter.js
import express from "express";
import Book from "../models/Book.js";
export const router = express.Router();
// it is /books route [view all Books]
router.get("/", async (req, res) => {
try {
const books = await Book.find();
res.status(200).json({ count: books.length, body: books });
} catch (error) {}
res.status(404).send({ message: "Cannot Get the Books" });
});
//insert a new Book [Write]
router.post("/add-book", async (req, res) => {
const { title, author, publishedYear } = req.body;
//validate inputs for null
if (title && author && publishedYear) {
//insert a new Book
const newBook = {
title: title,
author: author,
publishedYear: publishedYear,
};
const savedResponse = await Book.create(newBook);
res
.status(200)
.send({ message: "New Book Added Succesfully", data: savedResponse });
} else {
res.status(400).send({ message: "Please fill all required fields" });
}
});
// get only Particular Book [view only one ]
router.get("/:id", async (req, res) => {
const { id } = req.params;
try {
const book = await Book.findById(id);
res.status(200).send(book);
} catch (error) {
res.status(400).send({ message: "Book Specified Not found" });
}
});
// update a book
router.put("/:id", async (req, res) => {
const { title, author, publishedYear } = req.body;
const { id } = req.params;
//validate inputs for null
if (title && author && publishedYear) {
//insert a new Book
const updatedBook = {
title: title,
author: author,
publishedYear: publishedYear,
};
const savedResponse = await Book.findByIdAndUpdate(id, updatedBook);
res
.status(200)
.send({
message: "New Book Added Succesfully",
data: await Book.findById(id),
});
} else {
res.status(400).send({ message: "Cannot Update the book, Not Found" });
}
});
router.delete("/:id", async (req, res) => {
const { id } = req.params;
try {
const result = await Book.findByIdAndDelete(id);
res.status(200).send({ message: "Deleted Book Succesfully" });
} catch (error) {
res.status(400).send({ message: "Not found to Delete" });
}
});
Using Postman to test these endpoints,