CRUD Operations
The Four Pillars of Data Management
Explanation
What is CRUD?
CRUD stands for Create, Read, Update, Delete - the four basic operations you can perform on data. Whether you're building a todo app, social network, or enterprise system, everything comes back to CRUD.
Think of CRUD like the basic verbs of data:
- Create: Add new data (like posting a tweet)
- Read: Retrieve existing data (like viewing your feed)
- Update: Modify existing data (like editing a post)
- Delete: Remove data (like deleting a comment)
HTTP Methods Map to CRUD
| Operation | HTTP Method | SQL Command | Description | |-----------|------------|-------------|-------------| | Create | POST | INSERT | Add new record | | Read | GET | SELECT | Retrieve records | | Update | PUT/PATCH | UPDATE | Modify record | | Delete | DELETE | DELETE | Remove record |
Why This Matters
Understanding CRUD is essential because:
- Every database interaction boils down to CRUD
- REST APIs are built around CRUD operations
- Most application features are CRUD at their core
- Job interviews frequently ask about CRUD implementations
Demonstration
Example 1: CRUD with an Array (In-Memory)
// Our "database" - an array
let users = [
{ id: 1, name: "Arthur", email: "arthur@bpc.com" },
{ id: 2, name: "Sarah", email: "sarah@example.com" }
];
// CREATE - Add a new user
const createUser = (name, email) => {
const newUser = {
id: users.length + 1,
name,
email
};
users.push(newUser);
return newUser;
};
// READ - Get all users
const getAllUsers = () => users;
// READ - Get user by ID
const getUserById = (id) => {
return users.find(user => user.id === id);
};
// UPDATE - Modify a user
const updateUser = (id, updates) => {
const index = users.findIndex(user => user.id === id);
if (index === -1) return null;
users[index] = { ...users[index], ...updates };
return users[index];
};
// DELETE - Remove a user
const deleteUser = (id) => {
const index = users.findIndex(user => user.id === id);
if (index === -1) return false;
users.splice(index, 1);
return true;
};
// Usage:
console.log(createUser("Mike", "mike@test.com"));
console.log(getAllUsers());
console.log(updateUser(1, { name: "Big Poppa" }));
console.log(deleteUser(2));
Example 2: CRUD with Express.js REST API
const express = require('express');
const app = express();
app.use(express.json());
let todos = [];
let nextId = 1;
// CREATE - POST /todos
app.post('/todos', (req, res) => {
const todo = {
id: nextId++,
text: req.body.text,
completed: false,
createdAt: new Date()
};
todos.push(todo);
res.status(201).json(todo);
});
// READ ALL - GET /todos
app.get('/todos', (req, res) => {
res.json(todos);
});
// READ ONE - GET /todos/:id
app.get('/todos/:id', (req, res) => {
const todo = todos.find(t => t.id === parseInt(req.params.id));
if (!todo) return res.status(404).json({ error: 'Not found' });
res.json(todo);
});
// UPDATE - PUT /todos/:id
app.put('/todos/:id', (req, res) => {
const index = todos.findIndex(t => t.id === parseInt(req.params.id));
if (index === -1) return res.status(404).json({ error: 'Not found' });
todos[index] = { ...todos[index], ...req.body };
res.json(todos[index]);
});
// DELETE - DELETE /todos/:id
app.delete('/todos/:id', (req, res) => {
const index = todos.findIndex(t => t.id === parseInt(req.params.id));
if (index === -1) return res.status(404).json({ error: 'Not found' });
todos.splice(index, 1);
res.status(204).send();
});
app.listen(3000);
Key Takeaways:
- POST returns 201 (Created) with the new resource
- GET returns 200 with the data
- PUT returns 200 with the updated resource
- DELETE returns 204 (No Content)
- Always validate and handle errors
Imitation
Challenge 1: Add Search to Read
Task: Modify the getAllUsers function to accept an optional search query that filters by name.
getAllUsers("art"); // Returns users with "art" in their name
getAllUsers(); // Returns all users
Solution
const getAllUsers = (search = "") => {
if (!search) return users;
return users.filter(user =>
user.name.toLowerCase().includes(search.toLowerCase())
);
};
Challenge 2: Add Soft Delete
Task: Instead of actually removing users, implement a "soft delete" that marks them as deleted but keeps the data.
Solution
const softDeleteUser = (id) => {
const user = users.find(u => u.id === id);
if (!user) return false;
user.deleted = true;
user.deletedAt = new Date();
return true;
};
const getAllUsers = (includeDeleted = false) => {
if (includeDeleted) return users;
return users.filter(u => !u.deleted);
};
Practice
Exercise 1: Build a Notes API
Difficulty: Beginner
Task: Create CRUD operations for a notes app with:
id,title,content,createdAt,updatedAt
Requirements:
createNote(title, content)- Create new notegetNotes()- Get all notesgetNoteById(id)- Get single noteupdateNote(id, updates)- Update note, set updatedAtdeleteNote(id)- Delete note
Exercise 2: Add Pagination
Difficulty: Intermediate
Task: Modify your READ operation to support pagination.
getNotes({ page: 1, limit: 10 }); // Returns first 10 notes
getNotes({ page: 2, limit: 10 }); // Returns notes 11-20
Requirements:
- Accept
pageandlimitparameters - Return total count along with results
- Handle edge cases (invalid page, empty results)
Summary
What you learned:
- CRUD = Create, Read, Update, Delete
- How CRUD maps to HTTP methods and SQL
- Implementing CRUD with arrays and Express
- Best practices for API responses
Next Steps:
- Read: REST API Design
- Practice: Build a full CRUD API with a database
- Build: Create a bookmark manager with CRUD operations
