DEV Community

ncutixavier
ncutixavier

Posted on โ€ข Edited on

1 1 1

๐Ÿ“ CRUD Operation with Node.js, Express & MongoDB

This guide teaches how to build a simple Blog Article CRUD API using:

  • Node.js โ€“ runtime to run JavaScript on the server
  • Express โ€“ web framework for building APIs
  • MongoDB โ€“ NoSQL database
  • Mongoose โ€“ MongoDB ODM (object-document mapper)

๐Ÿ› ๏ธ Step 1: Setup the Project

1. Create a folder and initialize npm:

mkdir blog-crud && cd blog-crud
npm init -y
Enter fullscreen mode Exit fullscreen mode

2. Install required packages:

npm install express mongoose body-parser
Enter fullscreen mode Exit fullscreen mode
  • express: Web framework
  • mongoose: Connect and interact with MongoDB
  • body-parser: Parse incoming JSON request bodies

๐Ÿ“ Step 2: Project Structure

Organize your project files like this:

blog-crud/
โ”œโ”€โ”€ models/
โ”‚   โ””โ”€โ”€ Article.js        # Mongoose schema
โ”œโ”€โ”€ routes/
โ”‚   โ””โ”€โ”€ articles.js       # Route handlers
โ”œโ”€โ”€ server.js             # Main app entry
โ”œโ”€โ”€ package.json
Enter fullscreen mode Exit fullscreen mode

๐Ÿš€ Step 3: Create the Express Server (server.js)

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const articleRoutes = require('./routes/articles');

const app = express();

// Middleware to parse JSON
app.use(bodyParser.json());

// Route prefix: All article routes will start with /api/articles
app.use('/api/articles', articleRoutes);

// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/blog_crud', {
  useNewUrlParser: true,
  useUnifiedTopology: true
}).then(() => console.log('โœ… MongoDB Connected'))
  .catch(err => console.error('โŒ DB Connection Error:', err));

// Start the server
app.listen(3000, () => console.log('๐Ÿš€ Server running at http://localhost:3000'));
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • This is your main app file.
  • It sets up Express, connects to MongoDB, and loads article routes.

๐Ÿ“ฆ Step 4: Create the Article Schema (models/Article.js)

const mongoose = require('mongoose');

const articleSchema = new mongoose.Schema({
  title: String,
  content: String,
  author: String,
  createdAt: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('Article', articleSchema);
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Defines the structure of each Blog Article in the database.
  • Includes fields like title, content, author, and createdAt.

๐Ÿ” Step 5: Create CRUD Routes (routes/articles.js)

const express = require('express');
const router = express.Router();
const Article = require('../models/Article');
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”น 1. Create a new Article (POST /api/articles)

router.post('/', async (req, res) => {
  try {
    const article = await Article.create(req.body);
    res.status(201).json(article);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});
Enter fullscreen mode Exit fullscreen mode

Accepts JSON { title, content, author } and stores it in the database.


๐Ÿ”น 2. Read All Articles (GET /api/articles)

router.get('/', async (req, res) => {
  try {
    const articles = await Article.find();
    res.json(articles);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});
Enter fullscreen mode Exit fullscreen mode

Returns all articles stored in the database.


๐Ÿ”น 3. Read a Single Article by ID (GET /api/articles/:id)

router.get('/:id', async (req, res) => {
  try {
    const article = await Article.findById(req.params.id);
    if (!article) return res.status(404).json({ message: 'Not found' });
    res.json(article);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});
Enter fullscreen mode Exit fullscreen mode

Fetches a specific article using its ID.


๐Ÿ”น 4. Update an Article (PUT /api/articles/:id)

router.put('/:id', async (req, res) => {
  try {
    const updated = await Article.findByIdAndUpdate(
      req.params.id,
      req.body,
      { new: true } // return the updated document
    );
    if (!updated) return res.status(404).json({ message: 'Not found' });
    res.json(updated);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});
Enter fullscreen mode Exit fullscreen mode

Edits article details like title or content.


๐Ÿ”น 5. Delete an Article (DELETE /api/articles/:id)

router.delete('/:id', async (req, res) => {
  try {
    const deleted = await Article.findByIdAndDelete(req.params.id);
    if (!deleted) return res.status(404).json({ message: 'Not found' });
    res.json({ message: 'โœ… Article deleted' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});
Enter fullscreen mode Exit fullscreen mode

Deletes the selected article from the database.


Finally routes/articles.js

const express = require('express');
const router = express.Router();
const Article = require('../models/Article');

// โœ… Create an article
router.post('/', async (req, res) => {
  try {
    const article = await Article.create(req.body);
    res.status(201).json(article);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

// ๐Ÿ“– Get all articles
router.get('/', async (req, res) => {
  try {
    const articles = await Article.find();
    res.json(articles);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ๐Ÿ“„ Get a single article by ID
router.get('/:id', async (req, res) => {
  try {
    const article = await Article.findById(req.params.id);
    if (!article) return res.status(404).json({ message: 'Not found' });
    res.json(article);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// โœ๏ธ Update an article
router.put('/:id', async (req, res) => {
  try {
    const updated = await Article.findByIdAndUpdate(req.params.id, req.body, { new: true });
    if (!updated) return res.status(404).json({ message: 'Not found' });
    res.json(updated);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

// โŒ Delete an article
router.delete('/:id', async (req, res) => {
  try {
    const deleted = await Article.findByIdAndDelete(req.params.id);
    if (!deleted) return res.status(404).json({ message: 'Not found' });
    res.json({ message: 'Article deleted' });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

module.exports = router;


Enter fullscreen mode Exit fullscreen mode

๐Ÿงช Step 6: Testing the API

Use tools like Postman, Insomnia, or curl:

  • Create:
  curl -X POST http://localhost:3000/api/articles \
    -H "Content-Type: application/json" \
    -d '{"title": "My First Blog", "content": "Hello world!", "author": "Xavier"}'
Enter fullscreen mode Exit fullscreen mode
  • Read All:
  curl http://localhost:3000/api/articles
Enter fullscreen mode Exit fullscreen mode
  • Read One:
  curl http://localhost:3000/api/articles/<article_id>
Enter fullscreen mode Exit fullscreen mode
  • Update:
  curl -X PUT http://localhost:3000/api/articles/<article_id> \
    -H "Content-Type: application/json" \
    -d '{"title": "Updated Title"}'
Enter fullscreen mode Exit fullscreen mode
  • Delete:
  curl -X DELETE http://localhost:3000/api/articles/<article_id>
Enter fullscreen mode Exit fullscreen mode

โœ… Final Notes

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly โ€” using the tools and languages you already love!

Learn More

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free โ†’