In this tutorial, we will learn how to build a RESTful API using Node.js and MongoDB to perform CRUD operations. CRUD operations are essential for interacting with databases and are fundamental to web development.
Prerequisites
Before we begin, ensure you have the following installed on your system:
- Node.js (with npm or yarn)
- MongoDB (Community Edition)
Step 1: Setting Up Your Environment
Initialize a Node.js Project
- Create a new directory for your project.
- Open a terminal or command prompt and navigate to your project directory.
mkdir node-mongodb-crud-api
cd node-mongodb-crud-api
- Initialize a new Node.js project using npm.
npm init -y
Install necessary packages:
- Express: For building web APIs.
- Mongoose: MongoDB object modeling tool.
npm install express mongoose
Create a MongoDB Database
- Ensure MongoDB is running on your local machine or provide connection details for a remote MongoDB server.
Step 2: Define the MongoDB Schema
Create a Mongoose Schema
- Define the structure of our MongoDB documents using Mongoose Schema in a new file
models/Book.js
.
// models/Book.js
const mongoose = require('mongoose');
const bookSchema = new mongoose.Schema({
title: { type: String, required: true },
author: { type: String, required: true },
published_date: { type: Date, default: Date.now },
pages: { type: Number, required: true },
language: { type: String, required: true }
});
module.exports = mongoose.model('Book', bookSchema);
Step 3: Implementing CRUD Operations
Create Operation (POST Method)
- Implement a route to create new books in MongoDB in
routes/books.js
.
// routes/books.js
const express = require('express');
const router = express.Router();
const Book = require('../models/Book');
// POST /books - Create a new book
router.post('/', async (req, res) => {
try {
const book = await Book.create(req.body);
res.status(201).json(book);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
module.exports = router;
Read Operation (GET Method)
- Implement routes to retrieve books from MongoDB.
// routes/books.js
// GET /books - Retrieve all books
router.get('/', async (req, res) => {
try {
const books = await Book.find();
res.json(books);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
// GET /books/:id - Retrieve a specific book by ID
router.get('/:id', getBook, (req, res) => {
res.json(res.book);
});
async function getBook(req, res, next) {
try {
const book = await Book.findById(req.params.id);
if (book == null) {
return res.status(404).json({ message: 'Cannot find book' });
}
res.book = book;
next();
} catch (err) {
return res.status(500).json({ message: err.message });
}
}
Update Operation (PUT/PATCH Methods)
- Implement routes to update existing books in MongoDB.
// routes/books.js
// PUT /books/:id - Update a book by ID
router.put('/:id', getBook, async (req, res) => {
if (req.body.title != null) {
res.book.title = req.body.title;
}
if (req.body.author != null) {
res.book.author = req.body.author;
}
if (req.body.published_date != null) {
res.book.published_date = req.body.published_date;
}
if (req.body.pages != null) {
res.book.pages = req.body.pages;
}
if (req.body.language != null) {
res.book.language = req.body.language;
}
try {
const updatedBook = await res.book.save();
res.json(updatedBook);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
Delete Operation (DELETE Method)
- Implement routes to delete books from MongoDB.
// routes/books.js
// DELETE /books/:id - Delete a book by ID
router.delete('/:id', getBook, async (req, res) => {
try {
await res.book.remove();
res.json({ message: 'Deleted book' });
} catch (err) {
res.status(500).json({ message: err.message });
}
});
Step 4: Error Handling and Validation
Error Handling Middleware
- Implement middleware to handle errors in
app.js
`.
// app.js
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const booksRouter = require('./routes/books');
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/node-mongodb-crud-api', {
useNewUrlParser: true,
useUnifiedTopology: true
});
const db = mongoose.connection;
db.on('error', (err) => console.error('MongoDB connection error:', err));
db.once('open', () => console.log('Connected to MongoDB'));
app.use('/books', booksRouter);
app.listen(3000, () => console.log('Server started on http://localhost:3000'));
Data Validation
- Use Mongoose schema validation for required fields and data types in
models/Book.js
`.
// models/Book.js
const bookSchema = new mongoose.Schema({
title: { type: String, required: true },
author: { type: String, required: true },
published_date: { type: Date, default: Date.now },
pages: { type: Number, required: true },
language: { type: String, required: true }
});
Step 5: Testing Your APIs
Use Postman or Insomnia
- Test each CRUD operation using API testing tools to verify functionality.