Loading

Quipoin Menu

Learn • Practice • Grow

express-js / CRUD Operations with Database
tutorial

CRUD Operations with Database

Now that you know how to connect to databases, it's time to build a complete **CRUD** application. CRUD stands for Create, Read, Update, Delete – the four basic operations for persistent storage. In this chapter, we'll build a complete REST API for a simple resource (like products or posts) using Express and a database.

What is CRUD?

OperationHTTP MethodDescription
CreatePOSTAdd a new resource
ReadGETRetrieve resources (single or list)
UpdatePUT / PATCHModify an existing resource
DeleteDELETERemove a resource

Think of CRUD as the foundation of any data-driven application. Almost everything you build will involve these four operations.

Project Setup
mkdir crud-api
cd crud-api
npm init -y
npm install express mongoose dotenv
npm install --save-dev nodemon

Complete CRUD Example with MongoDB/Mongoose

1. Model (models/Product.js)
const mongoose = require('mongoose');

const productSchema = new mongoose.Schema({
  name: { type: String, required: true, trim: true },
  price: { type: Number, required: true, min: 0 },
  description: { type: String, maxlength: 500 },
  category: { type: String, required: true },
  inStock: { type: Boolean, default: true },
  createdAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model('Product', productSchema);

2. Database Connection (config/db.js)
const mongoose = require('mongoose');

const connectDB = async () => {
  try {
    await mongoose.connect(process.env.MONGODB_URI);
    console.log('MongoDB connected');
  } catch (err) {
    console.error(err);
    process.exit(1);
  }
};

module.exports = connectDB;

3. Complete CRUD Routes (routes/products.js)
const express = require('express');
const Product = require('../models/Product');
const router = express.Router();

<!-- CREATE: POST /products -->
router.post('/', async (req, res) => {
  try {
    const product = new Product(req.body);
    const savedProduct = await product.save();
    res.status(201).json(savedProduct);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

<!-- READ ALL: GET /products -->
router.get('/', async (req, res) => {
  try {
    const products = await Product.find().sort({ createdAt: -1 });
    res.json(products);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

<!-- READ SINGLE: GET /products/:id -->
router.get('/:id', async (req, res) => {
  try {
    const product = await Product.findById(req.params.id);
    if (!product) {
      return res.status(404).json({ error: 'Product not found' });
    }
    res.json(product);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

<!-- UPDATE: PUT /products/:id -->
router.put('/:id', async (req, res) => {
  try {
    const product = await Product.findByIdAndUpdate(
      req.params.id,
      req.body,
      { new: true, runValidators: true }
    );
    if (!product) {
      return res.status(404).json({ error: 'Product not found' });
    }
    res.json(product);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

<!-- DELETE: DELETE /products/:id -->
router.delete('/:id', async (req, res) => {
  try {
    const product = await Product.findByIdAndDelete(req.params.id);
    if (!product) {
      return res.status(404).json({ error: 'Product not found' });
    }
    res.status(204).send();
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

module.exports = router;

4. Main App File (app.js)
require('dotenv').config();
const express = require('express');
const connectDB = require('./config/db');
const productRoutes = require('./routes/products');

<!-- Connect to database -->
connectDB();

const app = express();
app.use(express.json());

<!-- Routes -->
app.use('/api/products', productRoutes);

<!-- 404 handler -->
app.use((req, res) => {
  res.status(404).json({ error: 'Route not found' });
});

<!-- Error handler -->
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Internal server error' });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Two Minute Drill

  • CRUD = Create (POST), Read (GET), Update (PUT), Delete (DELETE).
  • Always validate input and handle errors gracefully.
  • Use appropriate HTTP status codes (201 for created, 404 for not found, etc.).
  • Organize routes using Express Router for clean code.
  • Test your API with tools like Postman or Insomnia.

Need more clarification?

Drop us an email at career@quipoinfotech.com