For many developers, the choice of database quietly defines how flexible an application’s architecture can be. If you’re used to relational databases like MySQL or PostgreSQL, your first contact with MongoDB often feels like a mental model shift.
This post walks through why MongoDB looks the way it does and how to perform basic CRUD operations, with a focus on how its document model maps to real application needs.
Thinking in Tables: The Relational World
In relational databases, data lives in rows and columns, much like a spreadsheet. You define the schema up front:
- Every row must conform to the table definition.
- Columns are typed and fixed unless you run a migration.
This gives you:
- Strong consistency guarantees.
- Rigid, well‑structured data models.
But it also means:
- Schema changes can be painful at scale.
- Adding a new column to a billion‑row table can require long migrations and potential downtime.
In fast‑moving products where requirements evolve weekly, this rigidity becomes a noticeable bottleneck.
NoSQL, or “Not Only SQL”
Despite the name, NoSQL isn’t about rejecting SQL. It’s better understood as “Not Only SQL”:
- You don’t throw away relational databases.
- You add new storage options to your toolbox.
For social feeds, game logs, IoT data, and other semi‑structured or rapidly evolving workloads, a more flexible model can be a better fit. MongoDB is a prime example in the document‑oriented database family.
Core Concept: Documents and Collections
MongoDB shifts the unit of storage from rows to documents.
Documents
A document is the smallest data unit in MongoDB. It resembles a JSON object, but internally MongoDB uses BSON (Binary JSON):
- Binary format for faster read/write.
- Supports types that plain JSON can’t (dates, binary data, etc.).
The real strength of documents is nesting:
- You can embed objects and arrays directly.
- No need to normalize everything into separate tables with joins.
Example: E‑Commerce Order Document
{
// Unique identifier, similar to a primary key
"_id": ObjectId("64b8f1e2a9b3c5d6e7f8a9b0"),
// Date type stored natively
"created_at": ISODate("2024-05-20T09:30:00Z"),
"status": "Processing",
// Embedded object: no need for a separate addresses table
"delivery_info": {
"country": "France",
"city": "Paris",
"detail": "Avenue des Champs Elysées"
},
// Array of embedded documents
"cart_items": [
{
"sku": "KB-MECHANICAL-01",
"count": 1,
"unit_price": 599.0
},
{
"sku": "MOUSE-PAD-XL",
"count": 2,
"unit_price": 49.5
}
]
}
Here:
- Order metadata, delivery info, and line items live in a single document.
- Reads are often a single round‑trip, which maps nicely to many API use cases.
Collections
If documents are like rows, then collections are roughly equivalent to tables.
Key differences:
- Collections have a dynamic schema.
- Documents in the same collection don’t need the exact same fields.
For example, in a users collection:
- Some documents might have
wechat_id. - Others might only have
emailandgithub_username.
This flexibility lets your data model evolve alongside your code without mandatory migrations for every change.
The _id Field
Every document must have an _id:
- Acts as the primary key.
- If you don’t specify one, MongoDB auto‑generates an
ObjectId. -
ObjectIdincludes a timestamp component, so you can infer creation time from it if needed.
CRUD Basics in MongoDB
Assume you’re connected to a MongoDB instance (via mongosh or a GUI). The examples below operate on an employees collection.
Create: Insert Documents
MongoDB provides insertOne and insertMany.
Insert a Single Document
// Add a new employee to the "employees" collection
db.employees.insertOne({
name: "Jack",
department: "Engineering",
is_manager: false,
skills: ["Java", "Docker"],
onboard_date: new Date()
})
Insert Multiple Documents
// Add multiple interns in a single call
db.employees.insertMany([
{
name: "Mike",
role: "Intern",
age: 21,
mentor: "Jack"
},
{
name: "Tommy",
role: "Intern",
age: 22,
mentor: "Jack"
}
])
Read: Query Documents
Use findOne for a single match and find for multiple results.
Find One Document
// Find the first employee whose name is "Jack"
db.employees.findOne({ name: "Jack" })
Find Multiple Documents
// Find all employees older than 21
// $gt means "greater than"
db.employees.find({ age: { $gt: 21 } })
MongoDB supports a rich query language with operators like $lt, $in, $and, $or, and many more for complex filters.
Update: Modify Existing Documents
Updates combine:
- A filter (which documents to target).
- An update operator (what to change), commonly
$set.
Update a Single Document
// Promote "Tommy" to Junior Developer
db.employees.updateOne(
{ name: "Tommy" }, // Filter
{ $set: { role: "Junior Developer" } } // Update
)
Update Multiple Documents
// Add a default office location to employees missing a "location" field
db.employees.updateMany(
{ location: { $exists: false } },
{
$set: {
location: "New York",
wfh_allowed: true
}
}
)
You can also use operators like $inc, $push, $pull, and more for counters and array manipulation.
Delete: Remove Documents
Deletes follow the same pattern as queries: deleteOne and deleteMany.
Delete a Single Document
// Delete the first employee named "Mike"
db.employees.deleteOne({ name: "Mike" })
Delete Multiple Documents
// Delete all intern records
db.employees.deleteMany({ role: "Intern" })
⚠️ Warning:
db.employees.deleteMany({})with an empty filter will delete all documents in the collection. Use with extreme caution.
Building a Productive Local MongoDB Setup
Once you understand the document model and CRUD APIs, the next step is getting a reliable local environment.
Maintaining a local database stack by hand can be tedious:
- Installing MongoDB manually or via containers.
- Managing multiple versions across different projects.
- Handling port conflicts and data directories.
If you work on several services or legacy projects, you might need:
- MongoDB 5.x for one app.
- MongoDB 7.x or 8.x for a newer service.
Switching between these by hand quickly becomes error‑prone.
This is where a local platform that can install MongoDB with one click becomes valuable:
- You avoid wrestling with OS‑level installers and custom scripts.
- You can spin up multiple isolated instances per project.
- You keep your operating system clean while still having access to a full local database stack.
For example, using a tool that treats MongoDB as part of a broader dev stack lets you:
- Run different MongoDB versions side by side (e.g., 5.0 through 8.0).
- Combine MongoDB with MySQL, PostgreSQL, Redis, and others in the same local web dev environment.
- Manage services through a GUI instead of editing config files and service definitions by hand.
The result:
- Less time on setup and dependency management.
- More time designing schemas, writing queries, and building features.
If your goal is to learn MongoDB deeply or integrate it into multiple projects without fighting installs every time, offloading environment orchestration to tooling and focusing on the document model + CRUD logic is usually the most efficient path.
Final Thoughts
MongoDB’s document model is not “better” or “worse” than relational tables — it’s a different way to represent data:
- Documents and collections map naturally to many modern app data structures.
- Dynamic schemas and embedded documents shine in fast‑changing domains.
- CRUD operations are expressive without demanding rigid migrations up front.
Once your local MongoDB setup is as easy as clicking a button instead of following multi‑page install guides, you’ll find it much easier to experiment with real‑world schemas, indexes, and queries — which is where MongoDB really starts to pay off.


Top comments (0)