NoSQL CRUD Operations: Your Database Kitchen Adventure 🍳
Imagine you have a magical recipe box where you can store, find, change, and remove recipe cards anytime. That’s exactly what CRUD operations do in NoSQL databases! CRUD stands for Create, Read, Update, Delete — the four superpowers that let you manage your data.
Let’s explore each superpower with our recipe box!
1. Create and Insert Operations: Adding New Recipes
Think of it like: Writing a new recipe card and placing it in your box.
When you create or insert, you’re adding a brand new document (like a recipe card) to your collection (the recipe box).
How It Works
In NoSQL (like MongoDB), you insert documents like this:
// Add ONE recipe
db.recipes.insertOne({
name: "Chocolate Cake",
ingredients: ["flour", "sugar", "cocoa"],
time: 45
})
// Add MANY recipes at once
db.recipes.insertMany([
{ name: "Cookies", time: 20 },
{ name: "Brownies", time: 30 }
])
What happens?
- The database gives each document a unique ID (like a barcode on your recipe card)
- Your new data is now safely stored!
Key Points
insertOne()— adds one documentinsertMany()— adds multiple documents at once- Each document automatically gets a unique
_id
2. Read and Query Operations: Finding Your Recipes
Think of it like: Looking through your recipe box to find what you want.
Reading is how you ask questions to your database and get answers back.
Simple Queries
// Find ALL recipes
db.recipes.find()
// Find ONE specific recipe
db.recipes.findOne({ name: "Chocolate Cake" })
// Find recipes that take less than 30 minutes
db.recipes.find({ time: { $lt: 30 } })
Query Operators (Your Search Tools)
| Operator | Meaning | Example |
|---|---|---|
$eq |
Equals | { time: { $eq: 30 } } |
$gt |
Greater than | { time: { $gt: 20 } } |
$lt |
Less than | { time: { $lt: 60 } } |
$in |
In a list | { name: { $in: ["Cake", "Pie"] } } |
Real example: “Show me all recipes with chocolate that take under an hour”
db.recipes.find({
ingredients: "chocolate",
time: { $lt: 60 }
})
3. Document Projections: Picking What to Show
Think of it like: When someone asks for a recipe, you only read them the parts they need — not the whole card!
Projections let you choose which fields to include or exclude in your results.
How Projections Work
// Show ONLY name and time (exclude everything else)
db.recipes.find(
{},
{ name: 1, time: 1 }
)
// Show everything EXCEPT ingredients
db.recipes.find(
{},
{ ingredients: 0 }
)
The rules:
1means include this field0means exclude this field- The
_idfield shows by default (use_id: 0to hide it)
Why Use Projections?
- Faster: Less data to transfer
- Cleaner: Only get what you need
- Safer: Hide sensitive information
// Perfect example: Get recipe names only
db.recipes.find({}, { name: 1, _id: 0 })
// Result: [{ name: "Cake" }, { name: "Cookies" }]
4. Update Operations: Changing Your Recipes
Think of it like: Erasing something on your recipe card and writing something new.
Updates let you modify existing documents without deleting and re-creating them.
Update Commands
// Update ONE recipe
db.recipes.updateOne(
{ name: "Chocolate Cake" },
{ $set: { time: 50 } }
)
// Update MANY recipes
db.recipes.updateMany(
{ time: { $lt: 20 } },
{ $set: { difficulty: "easy" } }
)
Update Operators (Your Editing Tools)
| Operator | What It Does | Example |
|---|---|---|
$set |
Set a field value | { $set: { time: 30 } } |
$inc |
Increase a number | { $inc: { views: 1 } } |
$push |
Add to an array | { $push: { tags: "yummy" } } |
$pull |
Remove from array | { $pull: { tags: "old" } } |
$unset |
Remove a field | { $unset: { temp: "" } } |
Real Example
// Add a new ingredient to our cake
db.recipes.updateOne(
{ name: "Chocolate Cake" },
{ $push: { ingredients: "vanilla" } }
)
5. Delete Operations: Removing Recipes
Think of it like: Taking a recipe card out of your box and throwing it away.
Delete operations permanently remove documents from your collection.
Delete Commands
// Delete ONE recipe
db.recipes.deleteOne({ name: "Old Recipe" })
// Delete MANY recipes
db.recipes.deleteMany({ time: { $gt: 120 } })
// Delete ALL recipes (careful!)
db.recipes.deleteMany({})
Important!
deleteOne()— removes the first matching documentdeleteMany()— removes ALL matching documents- There’s no undo! Once deleted, it’s gone forever
// Delete all recipes without ratings
db.recipes.deleteMany({ rating: { $exists: false } })
6. Tombstones: The Ghost Markers
Think of it like: Instead of throwing away a recipe, you put a “DO NOT USE” sticker on it.
A tombstone is a marker that says “this data was deleted” without actually removing it immediately.
Why Use Tombstones?
graph TD A["Delete Request"] --> B{Hard Delete?} B -->|Yes| C["Data Gone Forever"] B -->|No - Soft Delete| D["Add Tombstone"] D --> E["Data Hidden But Recoverable"] E --> F["Clean Up Later"]
How Tombstones Work
// Instead of deleting, mark as deleted
db.recipes.updateOne(
{ name: "Old Cake" },
{
$set: {
deleted: true,
deletedAt: new Date()
}
}
)
// Query excludes tombstoned items
db.recipes.find({ deleted: { $ne: true } })
Tombstone Benefits
- Undo mistakes: Can recover “deleted” data
- Audit trail: Know what was deleted and when
- Sync systems: Tells other databases about deletions
- Compliance: Some laws require keeping records
7. Upsert Operations: The Smart Combo
Think of it like: “If the recipe exists, update it. If not, create a new one!”
Upsert = Update + Insert combined into one smart operation.
How Upsert Works
graph TD A["Upsert Command"] --> B{Document Exists?} B -->|Yes| C["Update It"] B -->|No| D["Insert New One"] C --> E["Done!"] D --> E
Upsert in Action
// The magic upsert option
db.recipes.updateOne(
{ name: "Mystery Dish" },
{ $set: { time: 25, category: "quick" } },
{ upsert: true } // <-- The magic!
)
What happens:
- If “Mystery Dish” exists → it gets updated
- If “Mystery Dish” doesn’t exist → a new document is created
Why Upsert is Amazing
- One command: No need to check if document exists first
- No duplicates: Prevents accidentally creating copies
- Atomic: Happens as one operation (safe and fast)
// Perfect for counters and tracking
db.pageViews.updateOne(
{ page: "/home" },
{ $inc: { count: 1 } },
{ upsert: true }
)
// First visit: creates { page: "/home", count: 1 }
// Second visit: updates to { page: "/home", count: 2 }
Summary: Your CRUD Superpowers
| Operation | Command | What It Does |
|---|---|---|
| Create | insertOne(), insertMany() |
Add new documents |
| Read | find(), findOne() |
Search and retrieve |
| Projection | { field: 1 } |
Choose what to show |
| Update | updateOne(), updateMany() |
Modify existing data |
| Delete | deleteOne(), deleteMany() |
Remove documents |
| Tombstone | Soft delete pattern | Mark as deleted |
| Upsert | { upsert: true } |
Update or create |
Remember This!
graph LR C["CREATE"] --> R["READ"] R --> U["UPDATE"] U --> D["DELETE"] D --> C style C fill:#4CAF50,color:#fff style R fill:#2196F3,color:#fff style U fill:#FF9800,color:#fff style D fill:#f44336,color:#fff
You now have all four superpowers:
- 🟢 Create — Add new data
- 🔵 Read — Find and retrieve data
- 🟠Update — Change existing data
- 🔴 Delete — Remove data
Plus the bonus powers:
- 📋 Projections — Show only what you need
- 👻 Tombstones — Soft delete with recovery
- ⚡ Upsert — Smart update-or-create
Congratulations! You’re now a CRUD master! 🎉
