The MERN stack, which includes MongoDB, Express, React, and Node.js, offers a reliable and quick solution to create modern web apps. In this post, we'll look at how to create a RESTful API with Express and MongoDB, the backend components of the MERN stack. This tutorial will show you how to set up a server, connect to a MongoDB database, and perform CRUD operations.
What are REST API's?
A RESTful API (Representational State Transfer) is a networked application design system that enables stateless communication between clients and servers. It performs CRUD (Create, Read, Update, Delete) actions on resources by using common HTTP methods such as GET, POST, PUT, and DELETE.
What is Express JS?
Express, a minimalist web framework for Node.js, simplifies the creation of robust APIs by providing a range of powerful features.
Initialize the Project
Create a project directory
mkdir mern-rest-api cd mern-rest-api
Initialize node.js
npm init -y
Install dependencies
npm i express mongoose cors
Project structure
Your project structure should look like this:
mern-rest-api/
├── node_modules/
├── package.json
├── server.js
└── config/
└── db.js
└── models/
└── user.model.js
└── routes/
└── user.routes.js
Connecting to MongoDB
Inside config
folder create a db.js
file.
// config/db.js
const mongoose = require('mongoose');
const connectDB = async () => {
try {
await mongoose.connect('mongodb://localhost:27017/mernapi');
console.log('MongoDB connected');
} catch (err) {
console.error(err.message);
process.exit(1);
}
};
module.exports = connectDB;
Setting up the express server
In the root directory create a server.js
file.
// server.js
const express = require('express');
const connectDB = require('./config/db');
const userRoutes = require('./routes/userRoutes.js');
const app = express();
// Connect Database
connectDB();
// Middleware
app.use(express.json({ extended: false }));
app.use(cors())
app.get('/', (req, res) => res.send('API Running'));
// Define Routes
app.use('/api/items', userRoutes);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port http://localhost:${PORT}`));
Creating the model
Inside models
folder create a file called user.model.js
// models/user.model.js
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
username: {
type: String,
required: [true, "Username is required"],
unique: true,
index: true,
minlength: [3, "Username must be at least 3 characters long"],
maxlength: [30, "Username cannot exceed 30 characters"],
match: [/^[a-zA-Z0-9_]+$/, "Username can only contain letters, numbers, and underscores"],
},
email: {
type: String,
required: [true, "Email is required"],
unique: true,
index: true,
match: [/\S+@\S+\.\S+/, "Please enter a valid email address"],
},
password: {
type: String,
required: [true, "Password is required"],
minlength: [6, "Password must be at least 6 characters long"],
maxlength: [128, "Password cannot exceed 128 characters"],
match: [/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{6,128}$/, "Password must include at least one uppercase letter, one lowercase letter, one number, and one special character"],
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("User", userSchema);
Defining Routes
Inside routes
folder create a file called userRoutes.js
// routes/items.js
const express = require('express');
const router = express.Router();
const User = require('../models/User.js');
// @route GET api/users
// @desc Get all users
// @access Public
router.get('/', async (req, res) => {
try {
const users = await User.find();
if (users.length === 0) {
return res.status(404).json({
success: false,
message: 'No users found',
data: null
});
}
res.status(200).json({
success: true,
message: 'Users retrieved successfully',
data: users
});
} catch (err) {
console.error('Error fetching users:', err.message);
res.status(500).json({
success: false,
message: 'Server Error',
data: null
});
}
});
// @route POST api/users
// @desc Create a user
// @access Public
router.post('/', async (req, res) => {
const { username, email, password } = req.body;
// Input validation
if (!username || !email || !password) {
return res.status(400).json({
success: false,
message: 'Please provide username, email, and password',
data: null
});
}
try {
const newUser = await User.create({
username,
email,
password
});
res.status(201).json({
success: true,
message: 'User created successfully',
data: newUser
});
} catch (err) {
console.error('Error creating user:', err.message);
res.status(500).json({
success: false,
message: 'Server Error',
data: null
});
}
});
// @route PUT api/users/:id
// @desc Update a user
// @access Public
router.put('/:id', async (req, res) => {
const { username, email, password } = req.body;
// Input validation
if (!username && !email && !password) {
return res.status(400).json({
success: false,
message: 'Please provide data to update',
data: null
});
}
try {
let user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({
success: false,
message: 'User not found',
data: null
});
}
// Update fields
if (username) user.username = username;
if (email) user.email = email;
if (password) user.password = password;
await user.save();
res.json({
success: true,
message: 'User updated successfully',
data: user
});
} catch (err) {
console.error('Error updating user:', err.message);
res.status(500).json({
success: false,
message: 'Server Error',
data: null
});
}
});
// @route DELETE api/users/:id
// @desc Delete a user
// @access Public
router.delete('/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({
success: false,
message: 'User not found',
data: null
});
}
await user.remove();
res.json({
success: true,
message: 'User removed',
data: null
});
} catch (err) {
console.error('Error deleting user:', err.message);
res.status(500).json({
success: false,
message: 'Server Error',
data: null
});
}
});
module.exports = router;
Running the server
Now that we have everything set up, you can start the server by running:
node server.js
Your API should now be running on http://localhost:5000
, and you can test the various endpoints using tools like Postman, Insomnia or curl.
If you found this post helpful, please like it and leave a comment with your ideas and questions.
Happy coding👋