Skip to content

3. MongoDB

A comprehensive MongoDB guide covering core concepts, advanced features, and how it handles things like foreign keys, relationships, and beyond β€” all in one place.

πŸ“˜ MongoDB Comprehensive Guide

1. πŸ”Ή What is MongoDB?

  • MongoDB is a NoSQL database that stores data in JSON-like documents (BSON).
  • It’s schema-less by default β€” meaning documents in a collection can have different structures.
  • Used for scalable, high-performance apps β€” especially in Node.js/Express ecosystems.

2. πŸ”Ή Basic Building Blocks

ConceptMongoDB Equivalent
DatabaseDatabase
TableCollection
RowDocument
ColumnField
Primary Key_id field (auto-gen)

3. πŸ”Ή Data Types

MongoDB supports:

  • String, Number, Boolean
  • Array, Object
  • Date
  • ObjectId (unique identifier)
  • Null

4. πŸ”Ή CRUD Operations

πŸ”Έ Create

db.users.insertOne({ name: "Alice", age: 30 })

πŸ”Έ Read

db.users.find({ name: "Alice" })

πŸ”Έ Update

db.users.updateOne({ name: "Alice" }, { $set: { age: 31 } })

πŸ”Έ Delete

db.users.deleteOne({ name: "Alice" })

5. πŸ”Ή Schema Design (Mongoose)

You can enforce structure using Mongoose in Node.js:

const userSchema = new mongoose.Schema({
name: String,
email: { type: String, unique: true },
age: Number
});

6. πŸ”Ή Relationships in MongoDB

MongoDB is non-relational, but you can model relationships in two ways:

A. Embedding (Denormalization)

{
name: "Alice",
orders: [
{ product: "Book", quantity: 2 },
{ product: "Pen", quantity: 5 }
]
}

βœ… Great for fast reads, fewer joins.

B. Referencing (Normalization)

// users
{ _id: ObjectId("u1"), name: "Alice" }
// orders
{ userId: ObjectId("u1"), product: "Book" }

You can manually β€œjoin” with populate() in Mongoose:

Order.find().populate('userId');

✨ How it works:

.populate('userId') works only if you’ve told Mongoose how userId is related in your schema.

So the key is setting up the reference properly.

βœ… Example: Setting Up the Relationship
models/User.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: String,
email: String
});
module.exports = mongoose.model('User', userSchema);
models/Order.js
const mongoose = require('mongoose');
const orderSchema = new mongoose.Schema({
product: String,
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User' // <--- THIS tells Mongoose to link with the User model
}
});
module.exports = mongoose.model('Order', orderSchema);

Now when you run this:

Order.find().populate('userId')

Mongoose:

  • Sees userId is a reference (ref: 'User')
  • Looks up the User model
  • Replaces userId with the actual User document
πŸ§ͺ Output Before .populate()
{
_id: "order1",
product: "Book",
userId: "662ac3f9d25a10a9f1b821ad"
}
βœ… Output After .populate()
{
_id: "order1",
product: "Book",
userId: {
_id: "662ac3f9d25a10a9f1b821ad",
name: "Alice",
email: "alice@example.com"
}
}

⚠️ Common Mistakes

  1. ❌ Forgetting ref: 'User' in the schema
  2. ❌ Using string instead of mongoose.Schema.Types.ObjectId
  3. ❌ The referenced document (User) doesn’t exist
  4. ❌ Typo in the model name (ref: 'user' instead of 'User')

7. πŸ”Ή Does MongoDB Support Foreign Keys?

Not natively like SQL.

MongoDB:

  • Doesn’t enforce foreign keys.
  • You can manually manage relations and use tools like Mongoose to simulate joins.

In Mongoose:

const orderSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
product: String
});

8. πŸ”Ή Indexes

Indexes improve query performance.

db.users.createIndex({ email: 1 }, { unique: true });

Mongoose:

email: { type: String, unique: true }

9. πŸ”Ή Aggregation Framework

Powerful for data analysis, transformation, and group operations.

db.orders.aggregate([
{ $match: { status: "complete" } },
{ $group: { _id: "$userId", total: { $sum: "$amount" } } }
])

10. πŸ”Ή Transactions (ACID Support)

  • MongoDB supports multi-document ACID transactions in replica sets (4.0+).
  • Use them when you really need SQL-like reliability.
const session = await mongoose.startSession();
session.startTransaction();
try {
await User.create([{ name: 'Bob' }], { session });
await Order.create([{ product: 'Book' }], { session });
await session.commitTransaction();
} catch (err) {
await session.abortTransaction();
}

11. πŸ”Ή Advanced Features

FeatureDescription
πŸ” Role-based AccessManage users/roles with db.createUser()
☁️ MongoDB AtlasCloud-hosted MongoDB with backups, scaling, monitoring
🚦 ValidationEnforce schemas using Mongoose or MongoDB validator rules
πŸ”„ Change StreamsReal-time event listeners for DB changes
πŸš€ Full-text SearchNative support for $text search and indexes

12. πŸ”Ή MongoDB vs SQL: Quick Comparison

FeatureMongoDBSQL (MySQL, Postgres)
Data FormatBSON (JSON-like)Tables (rows/columns)
SchemaFlexible (optional)Strict (defined)
RelationshipsManual (populate, ref)Foreign keys, joins
ScalabilityEasy to scale horizontally (shards)Can be harder to scale
PerformanceFast for unstructured dataGreat for relational data
  • MongoDB Compass: Visual GUI
  • MongoDB Atlas: Cloud DB hosting
  • Mongoose: ODM for Node.js
  • Robo 3T: Lightweight DB GUI
  • Postman: API testing