MongoDB is the “M” in MERN β the database that stores all of your application’s data. Unlike the relational databases you may have used before (MySQL, PostgreSQL, SQLite), MongoDB does not organise data into rigid tables with fixed columns and rows. Instead it stores data as flexible, JSON-like documents grouped into collections. This document model is a natural fit for JavaScript applications because the data format β essentially a JSON object β maps directly to the JavaScript objects you already work with in your code. In this lesson you will understand what MongoDB is, how it differs from relational databases, and why it is the standard database choice for the MERN stack.
Relational vs Document Databases
| Concept | Relational (MySQL / PostgreSQL) | MongoDB |
|---|---|---|
| Basic unit of storage | Row in a table | Document in a collection |
| Schema | Fixed β all rows must match the table schema | Flexible β documents in the same collection can have different fields |
| Data format | Typed columns (VARCHAR, INT, DATEβ¦) | JSON-like BSON objects with nested fields and arrays |
| Relationships | Foreign keys and JOIN operations | Embedded documents or ObjectId references |
| Query language | SQL (Structured Query Language) | MongoDB Query Language (MQL) β JSON-based operators |
| Scaling | Primarily vertical (bigger server) | Horizontal (sharding across many servers) |
| Transactions | ACID transactions β strong by default | ACID transactions supported (multi-document since v4.0) |
Why MongoDB Fits the MERN Stack
| Reason | Detail |
|---|---|
| Same data format | MongoDB stores BSON (Binary JSON) β your Node.js code works with plain JavaScript objects with no conversion needed |
| Schema flexibility | Early in development you can iterate on your data model without painful database migrations |
| JavaScript-friendly queries | MQL queries are JavaScript objects β { published: true, tags: 'mern' } β not SQL strings to construct and sanitise |
| Mongoose ODM | Mongoose bridges Node.js and MongoDB with schemas, validation, hooks, and a clean async API |
| Atlas free tier | MongoDB Atlas provides a permanently free cloud cluster β no infrastructure to manage for learning and small projects |
| JSON throughout | Data flows from MongoDB β Express β React as JSON with no transformation layer needed |
The MongoDB Data Model β A Blog Post Example
// In a relational database, this blog post spans THREE tables:
// posts table: post_id | title | body | author_id | created_at
// post_tags: post_id | tag_id
// tags table: tag_id | name
// In MongoDB, it is ONE document:
{
"_id": "64a1f2b3c8e4d5f6a7b8c9d0",
"title": "Getting Started with MERN",
"slug": "getting-started-with-mern",
"body": "The MERN stack is a powerful combination...",
"excerpt": "A complete guide to building full-stack apps.",
"author": {
"_id": "64a1f2b3c8e4d5f6a7b8c9d1",
"name": "Jane Smith",
"avatar": "https://cdn.example.com/jane.jpg"
},
"tags": ["mern", "javascript", "beginner"],
"published": true,
"featured": false,
"viewCount": 142,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
}
// The author is embedded β no JOIN needed to display a post with author info
MongoDB Architecture
MongoDB Server (mongod process β localhost:27017 or Atlas cluster)
β
βββ Database: blogdb
β βββ Collection: posts β like a table, but schema-flexible
β β βββ Document: { _id, title, body, author, tags, ... }
β β βββ Document: { _id, title, body, author, tags, ... }
β β βββ Document: { _id, title, body, ... } β can have extra fields
β β
β βββ Collection: users
β β βββ Document: { _id, name, email, password, role, ... }
β β
β βββ Collection: comments
β βββ Document: { _id, postId, author, body, createdAt }
β
βββ Database: admin β MongoDB system database (do not modify)
MongoDB vs MySQL β Blog Post Query
ββ MySQL: Get a post with author and tags ββββββββββββββββββββββββββββββββββββ
SELECT p.*, u.name, u.avatar, GROUP_CONCAT(t.name) AS tags
FROM posts p
JOIN users u ON p.author_id = u.id
LEFT JOIN post_tags pt ON p.id = pt.post_id
LEFT JOIN tags t ON pt.tag_id = t.id
WHERE p.slug = 'getting-started-with-mern'
GROUP BY p.id;
ββ MongoDB (Mongoose): Get the same post βββββββββββββββββββββββββββββββββββββ
await Post.findOne({ slug: 'getting-started-with-mern' })
.populate('author', 'name avatar');
// Tags are already embedded in the document β no JOIN needed
Common Mistakes
Mistake 1 β Choosing MongoDB for every project regardless of data shape
β Wrong β using MongoDB for data that is fundamentally relational:
Accounting software with double-entry bookkeeping, complex multi-table constraints,
and strict ACID requirements across dozens of related records
β A relational database (PostgreSQL) is a better fit here
β Correct β evaluate the data shape first. MongoDB is ideal for documents (blog posts, products, user profiles, activity logs). Relational databases are ideal for deeply interconnected, highly normalised data with complex integrity constraints.
Mistake 2 β Ignoring Mongoose schemas because MongoDB is “schemaless”
β Wrong β writing directly to MongoDB without any schema enforcement:
// Without schema β anything goes
db.collection('posts').insertOne({ title: 123, random_field: true });
// Now your posts collection has inconsistent documents
β Correct β always define a Mongoose schema. MongoDB’s flexibility is for the database layer β your application layer should always enforce structure.
Mistake 3 β Storing ObjectIds as strings in references
β Wrong β storing another document’s ID as a plain string:
{ author: "64a1f2b3c8e4d5f6a7b8c9d1" } // plain string β populate() won't work
β
Correct β use the ObjectId type for references so Mongoose’s populate() can resolve them:
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } // β
Quick Reference
| Concept | MongoDB Term | SQL Equivalent |
|---|---|---|
| The server process | mongod | mysqld / postgres |
| A database | Database | Database / Schema |
| A group of similar data | Collection | Table |
| A single record | Document | Row |
| A field in a record | Field | Column |
| Unique record identifier | _id (ObjectId) | Primary Key (INT / UUID) |
| Related record reference | ObjectId reference | Foreign Key |
| Query language | MQL (JSON-based) | SQL |