DEV Community

KISHAN RAMLAKHAN NISHAD
KISHAN RAMLAKHAN NISHAD

Posted on

A CRUD operation in the standard project structure for a Node.js backend application using Express.js and MongoDB.

Let's implement a CRUD operation in the standard project structure I provided above. We'll create a User model and perform basic Create, Read, Update, and Delete operations.

  1. Project Setup Install Dependencies:
npm init -y
npm install express mongoose dotenv cors helmet morgan jsonwebtoken bcryptjs
npm install --save-dev nodemon

Enter fullscreen mode Exit fullscreen mode

Folder Structure Recap:

/project-root
│
├── /src
│   ├── /config
│   ├── /controllers
│   ├── /middlewares
│   ├── /models
│   ├── /routes
│   ├── /services          # NEW: Business logic and database interaction
│   ├── /utils
│   └── app.js
│
├── .env
├── server.js
├── package.json
└── README.md

Enter fullscreen mode Exit fullscreen mode
  1. Setting Up CRUD Operations Step 1: Configure Environment and Server .env
PORT=5000
MONGO_URI=mongodb://localhost:27017/crud_db

Enter fullscreen mode Exit fullscreen mode

server.js

const app = require('./src/app');
const mongoose = require('mongoose');
require('dotenv').config();

const PORT = process.env.PORT || 5000;

mongoose.connect(process.env.MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => {
    console.log('MongoDB Connected');
    app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
}).catch(err => console.error('MongoDB connection error:', err));

Enter fullscreen mode Exit fullscreen mode

Step 2: Setup Express App
/src/app.js

const express = require('express');
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');
const userRoutes = require('./routes/userRoutes');
const { errorHandler } = require('./middlewares/errorMiddleware');

const app = express();

// Middlewares
app.use(helmet());
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());

// Routes
app.use('/api/users', userRoutes);

// Error Handling Middleware
app.use(errorHandler);

module.exports = app;

Enter fullscreen mode Exit fullscreen mode

Step 3: Create the User Model
/src/models/userModel.js

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: [true, 'Name is required']
    },
    email: {
        type: String,
        required: [true, 'Email is required'],
        unique: true
    },
    password: {
        type: String,
        required: [true, 'Password is required']
    }
}, { timestamps: true });

module.exports = mongoose.model('User', userSchema);

Enter fullscreen mode Exit fullscreen mode

step 4
Setting Up the Service Layer

Step a: Create the User Service
/src/services/userService.js

const User = require('../models/userModel');

// Service to create a new user
const createUser = async (userData) => {
    const user = new User(userData);
    return await user.save();
};

// Service to get all users
const getAllUsers = async () => {
    return await User.find();
};

// Service to get user by ID
const getUserById = async (userId) => {
    return await User.findById(userId);
};

// Service to update user by ID
const updateUser = async (userId, updateData) => {
    return await User.findByIdAndUpdate(userId, updateData, { new: true, runValidators: true });
};

// Service to delete user by ID
const deleteUser = async (userId) => {
    return await User.findByIdAndDelete(userId);
};

module.exports = {
    createUser,
    getAllUsers,
    getUserById,
    updateUser,
    deleteUser
};

Enter fullscreen mode Exit fullscreen mode

setp 5. Update the Controller to Use the Service Layer
/src/controllers/userController.js

const userService = require('../services/userService');

// CREATE - Add new user
exports.createUser = async (req, res, next) => {
    try {
        const user = await userService.createUser(req.body);
        res.status(201).json({ success: true, data: user });
    } catch (err) {
        next(err);
    }
};

// READ - Get all users
exports.getUsers = async (req, res, next) => {
    try {
        const users = await userService.getAllUsers();
        res.status(200).json({ success: true, data: users });
    } catch (err) {
        next(err);
    }
};

// READ - Get user by ID
exports.getUserById = async (req, res, next) => {
    try {
        const user = await userService.getUserById(req.params.id);
        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }
        res.status(200).json({ success: true, data: user });
    } catch (err) {
        next(err);
    }
};

// UPDATE - Update user by ID
exports.updateUser = async (req, res, next) => {
    try {
        const user = await userService.updateUser(req.params.id, req.body);
        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }
        res.status(200).json({ success: true, data: user });
    } catch (err) {
        next(err);
    }
};

// DELETE - Remove user by ID
exports.deleteUser = async (req, res, next) => {
    try {
        const user = await userService.deleteUser(req.params.id);
        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }
        res.status(200).json({ success: true, message: 'User deleted successfully' });
    } catch (err) {
        next(err);
    }
};

Enter fullscreen mode Exit fullscreen mode

setp 6. Route Setup
The routes remain the same as before.

/src/routes/userRoutes.js

const express = require('express');
const router = express.Router();
const {
    createUser,
    getUsers,
    getUserById,
    updateUser,
    deleteUser
} = require('../controllers/userController');

// Create a new user
router.post('/', createUser);

// Get all users
router.get('/', getUsers);

// Get a user by ID
router.get('/:id', getUserById);

// Update a user by ID
router.put('/:id', updateUser);

// Delete a user by ID
router.delete('/:id', deleteUser);

module.exports = router;

Enter fullscreen mode Exit fullscreen mode

Step 6: Error Handling Middleware

/src/middlewares/errorMiddleware.js

exports.errorHandler = (err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({
        success: false,
        message: err.message || 'Server Error'
    });
};

Enter fullscreen mode Exit fullscreen mode

step: 7

Make sure MongoDB is running and then start the server:

npx nodemon server.js

Enter fullscreen mode Exit fullscreen mode

step 8
Test the API Using Postman
Create a User (POST)
URL: http://localhost:5000/api/users
Body:

{
    "name": "Alice",
    "email": "alice@example.com",
    "password": "password123"
}

Enter fullscreen mode Exit fullscreen mode

Get All Users (GET)
URL: http://localhost:5000/api/users

Get a User by ID (GET)
URL: http://localhost:5000/api/users/{id}

Update a User (PUT)
URL: http://localhost:5000/api/users/{id}
Body:

{
    "name": "Alice Updated"
}

Enter fullscreen mode Exit fullscreen mode

Delete a User (DELETE)
URL: http://localhost:5000/api/users/{id}

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more