DEV Community

Tanmay Gupta
Tanmay Gupta

Posted on

Building Basic CRUD Routes in Express with MongoDB

Starting with what actually backend does... CRUD!!

CRUD stands for:

  • Create → Add new data
  • Read → Retrieve existing data
  • Update → Modify existing data
  • Delete → Remove data

This guide will walk you through implementing basic CRUD operations using Express.js and Mongoose.


Step 1: Define a Mongoose Model

Create a file at src/models/Post.js:

const mongoose = require('mongoose');

const postSchema = new mongoose.Schema({
  title: "{"
    type: String,
    required: true
  },
  body: {
    type: String,
    required: true
  }
}, { timestamps: true });

module.exports = mongoose.model('Post', postSchema);
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Controller Functions

Create a file at src/controllers/postController.js:

const Post = require('../models/Post');

// Create a new post
exports.createPost = async (req, res) => {
  try {
    const post = new Post(req.body);
    const saved = await post.save();
    res.status(201).json(saved);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
};

// Get all posts
exports.getAllPosts = async (req, res) => {
  try {
    const posts = await Post.find();
    res.json(posts);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
};

// Get a single post by ID
exports.getPostById = async (req, res) => {
  try {
    const post = await Post.findById(req.params.id);
    if (!post) return res.status(404).json({ error: 'Post not found' });
    res.json(post);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
};

// Update a post
exports.updatePost = async (req, res) => {
  try {
    const updated = await Post.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
      runValidators: true
    });
    if (!updated) return res.status(404).json({ error: 'Post not found' });
    res.json(updated);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
};

// Delete a post
exports.deletePost = async (req, res) => {
  try {
    const deleted = await Post.findByIdAndDelete(req.params.id);
    if (!deleted) return res.status(404).json({ error: 'Post not found' });
    res.json({ message: 'Post deleted successfully' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Define the Routes

Create a file at src/routes/postRoutes.js:

const express = require('express');
const router = express.Router();
const postController = require('../controllers/postController');

router.post('/', postController.createPost);
router.get('/', postController.getAllPosts);
router.get('/:id', postController.getPostById);
router.put('/:id', postController.updatePost);
router.delete('/:id', postController.deletePost);

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Step 4: Mount the Routes in app.js

Update your src/app.js or server.js:

const express = require('express');
const app = express();
const postRoutes = require('./routes/postRoutes');

app.use(express.json());
app.use('/api/posts', postRoutes);

module.exports = app;
Enter fullscreen mode Exit fullscreen mode

Testing the Routes

You can test these routes using tools like:

Endpoints:

  • POST /api/posts – Create a post
  • GET /api/posts – Get all posts
  • GET /api/posts/:id – Get post by ID
  • PUT /api/posts/:id – Update post
  • DELETE /api/posts/:id – Delete post

Example request body for creating a post:

{
  "title": "First Blog Post",
  "body": "This is the content of the blog post."
}
Enter fullscreen mode Exit fullscreen mode

Summary

You now have:

  • A Mongoose model (Post)
  • Controller functions for handling logic
  • Express routes for handling HTTP requests
  • A working CRUD API

This pattern keeps your code modular, scalable, and easy to maintain.

Top comments (6)

Collapse
 
nevodavid profile image
Nevo David

nice, seeing basic stuff laid out like this always helps me out tbh. you think the real challenge comes in keeping things clean as projects get bigger or is it more about picking the right structure up front?

Collapse
 
tanmay_dev profile image
Tanmay Gupta

so the thing is to start clean, writing clean code from start helps in debugging and also when collaborating and then as scale increases you need to maintain the cleanliness of code

Collapse
 
dotallio profile image
Dotallio

Really clear walkthrough! I like how you broke everything into controllers and routes, makes it so much easier to expand later.

Have you thought about adding authentication as a next step?

Collapse
 
tanmay_dev profile image
Tanmay Gupta

sure adding everything middlewares jwt bcrypt all in upcoming blogs

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

pretty cool walking through it like this, i always wonder though- you think it’s all about practicing with real projects or just messing around till it clicks?

Collapse
 
tanmay_dev profile image
Tanmay Gupta

thanks bro, so its a mix of both some messing around and yeah mainly real life projects some github repo search its all part of the process

Some comments may only be visible to logged-in visitors. Sign in to view all comments.