Dev Dissection — Week 2: Connecting Your API to MongoDB
Welcome back to Dev Dissection!
Last week, we built a simple TODO API using Node.js, Express, and TypeScript. This week, we’re going to persist our data by integrating a real database — MongoDB.
By the end of this lesson, your TODOs won’t vanish when the server restarts.
Prerequisites
Make sure you have:
- MongoDB installed locally or a free MongoDB Atlas cluster set up
- MongoDB compass or any tool that helps navigating DB
- The Week 1 TODO API working
- A .env file ready for storing secrets
- Basic familiarity with command line and JavaScript
SQL vs NoSQL (Quick Breakdown)
SQL (Relational):
Structured tables (like Excel sheets) with rows and columns. You define a schema up front.
Examples: MySQL, PostgreSQL.
NoSQL (Non-relational):
Flexible, nested documents (JSON-like). You can have varying data structures.
Example: MongoDB.
Feature | SQL | NoSQL (MongoDB) |
Schema | Strict, pre-defined | Flexible, dynamic |
Structure | Tables, rows | Collections, documents |
Query Lang | SQL | BSON-based (JSON-like) |
MongoDB is great when data structures evolve rapidly — perfect for early-stage projects and agile development.
Let’s Set Up MongoDB with Mongoose
Step 1: Install dependencies
npm install mongoose dotenv
npm install -D @types/mongoose
Step 2: Create a .env file
In your project root, add:
MONGO_URI=mongodb://localhost:27017/todos-dev |
Step 3: Update your src/index.ts
import express, { Request, Response } from 'express';
import cors from 'cors';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const PORT = 4000;
app.use(cors());
app.use(express.json());
// Connect to MongoDB
mongoose
.connect(process.env.MONGO_URI!)
.then(() => console.log('Connected to MongoDB'))
.catch((err) => console.error('MongoDB connection error:', err));
// Define interfaces for request bodies
interface CreateTodoBody {
task?: string;
}
interface UpdateTodoBody {
task?: string;
completed?: boolean;
}
// Define a Mongoose schema and model
const todoSchema = new mongoose.Schema(
{
task: { type: String, required: true },
completed: { type: Boolean, default: false },
},
{ timestamps: true },
);
const Todo = mongoose.model('Todo', todoSchema);
// CRUD Routes
// Create
app.post(
'/todos',
async (req: Request<{}, {}, CreateTodoBody>, res: Response) => {
try {
const task = req.body.task;
if (!task) {
res.status(400).json({ error: 'Task is required' });
return;
}
const newTodo = await Todo.create({ task: task });
res.status(201).json(newTodo);
} catch (err) {
res.status(400).json({ error: 'Failed to create TODO' });
}
},
);
// Read
app.get('/todos', async (_req: Request, res: Response) => {
const todos = await Todo.find();
res.status(200).json(todos);
});
// Update
app.put(
'/todos/:id',
async (req: Request<{ id: string }, {}, UpdateTodoBody>, res: Response) => {
try {
if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
res.status(400).json({ error: 'Invalid ID format' });
return;
}
if (!req.body) {
res.status(400).json({ error: 'Please send correct inputs' });
return;
}
const { task, completed } = req.body;
if (!task || completed) {
res.status(400).send('Please send correct inputs');
return;
}
const updated = await Todo.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
if (!updated) {
res.status(404).json({ error: 'Not found' });
return;
}
res.json(updated);
} catch (err) {
console.log(err);
res.status(400).json({ error: 'Failed to update TODO' });
}
},
);
// Delete
app.delete(
'/todos/:id',
async (req: Request<{ id: string }>, res: Response) => {
if (!mongoose.Types.ObjectId.isValid(req.params.id)) {
res.status(400).json({ error: 'Invalid ID format' });
return;
}
const deleted = await Todo.findByIdAndDelete(req.params.id);
if (!deleted) {
res.status(404).json({ error: 'Not found' });
return;
}
res.status(204).send('Todo was completed successfully');
},
);
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
Try it Out
Start your server:
npm run dev
Test endpoints using:
- Hoppscotch
- Postman
- Frontend (coming soon!)
What You Learned
This week, you:
- Learned SQL vs NoSQL basics
- Set up and configured MongoDB
- Used Mongoose to define models
- Built a persistent TODO API
Coming Up: React Frontend
In Week 3, we’ll:
- Build a React UI to interact with your API
- Use Axios or fetch to get data
- Show and update TODOs live