Sling Academy
Home/Node.js/Node + Express + Mongoose: CRUD example (Rest API)

Node + Express + Mongoose: CRUD example (Rest API)

Last updated: December 31, 2023

Introduction

This tutorial walks you through the setup of a REST API with a Node.js and Express backend, using Mongoose to facilitate database operations with MongoDB. Whether you’re new or experienced in backend development, this guide will provide step-by-step instructions as well as full code examples for creating, reading, updating, and deleting data. Let’s build a simple CRUD application together.

Setting Up the Project

Before diving into the code examples, you’ll need to set up your project environment. Make sure you have Node.js and npm installed. Then, create a new directory for your project and initialize it with npm init. Install the necessary dependencies with npm install express mongoose body-parser.

// Project setup
mkdir my-crud-api
 cd my-crud-api
npm init -y
npm install express mongoose body-parser

Creating the Model

Start by defining a Mongoose model that represents the schema for your data. Below is an example schema for a simple ‘Book’ model:

// Create a model
const mongoose = require('mongoose');

const bookSchema = new mongoose.Schema({
    title: String,
    author: String,
    year: Number
});

const Book = mongoose.model('Book', bookSchema);

Setting Up Express and Mongoose

After defining your model, set up Express and connect to your MongoDB database with Mongoose:

// Server setup
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');

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

// Database connection
c.onst db = 'your-mongodb-connection-string';
mongoose.connect(db, { useNewUrlParser: true, useUnifiedTopology: true });

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

Implementing CRUD Operations

Create (POST)

To add a new item to your database, you’ll need an endpoint to handle POST requests:

// POST endpoint
app.post('/books', async (req, res) => {
    const { title, author, year } = req.body;
    const book = new Book({ title, author, year });
    try {
        await book.save();
        res.status(201).send(book);
    } catch (error) {
        res.status(400).send(error);
    }
});

Read (GET)

To fetch data, create GET endpoints for listing all items and retrieving a single item by ID:

// GET endpoints
app.get('/books', async (req, res) => {
    const books = await Book.find();
    res.send(books);
});

app.get('/books/:id', async (req, res) => {
    try {
        const book = await Book.findById(req.params.id);
        res.send(book);
    } catch (error) {
        res.status(404).send({ message: 'Book not found' });
    }
});

Update (PUT)

Updating an item can be done by handling PUT requests:

// PUT endpoint
app.put('/books/:id', async (req, res) => {
    try {
        const book = await Book.findByIdAndUpdate(req.params.id, req.body, { new: true });
        res.send(book);
    } catch (error) {
        res.status(404).send({ message: 'Book not found' });
    }
});

Delete (DELETE)

To remove an item from the database, create a DELETE endpoint:

// DELETE endpoint
app.delete('/books/:id', async (req, res) => {
    try {
        const book = await Book.findByIdAndDelete(req.params.id);
        if (!book) return res.status(404).send({ message: 'Book not found' });
        res.status(200).send({ message: 'Book deleted' });
    } catch (error) {
        res.status(500).send(error);
    }
});

Error Handling and Middleware

Good API design includes proper error handling. Create middleware functions to handle errors and respond with appropriate HTTP status codes:

// Error handling middleware
app.use((err, req, res, next) => {
    res.status(500).send({ error: err.message });
});

Testing the API

Last but not least, test your API using tools like Postman or cURL. Make requests to each of your endpoints and ensure responses are as expected:

// Example cURL requests
curl -X POST -H 'Content-Type: application/json' -d '{"title":"New Book","author":"John Doe","year":2021}' http://localhost:3000/books
curl -X GET http://localhost:3000/books
curl -X PUT -H 'Content-Type: application/json' -d '{"year":2022}' http://localhost:3000/books/:id
curl -X DELETE http://localhost:3000/books/:id

Conclusion

In this tutorial, you’ve learned to set up a REST API for CRUD operations using Node.js, Express, and Mongoose. By following the examples provided, you can now build on this foundation to create your own robust APIs. Remember to test thoroughly and handle errors to ensure a stable backend for your applications.

Next Article: Node.js + Express: How to create an XML sitemap

Previous Article: Express + Handlebars: How to Render JSON Data

Series: Node.js & Express Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates