Showing posts with label Data Modeling. Show all posts
Showing posts with label Data Modeling. Show all posts

MongoDB Embedded Documents & Arrays Tutorial : Beginner to Expert


Embedded Documents & Arrays: Nested Magic Boxes in MongoDB

A Russian Doll Adventure - For Beginner to Expert Level


Imagine you have a big magic box (a document). Inside it, you can put smaller boxes (embedded documents) and treasure bags (arrays) that hold many items. No need to open separate boxes in another room.
This is called embedding in MongoDB. Instead of splitting data across many collections (like SQL tables with JOINs), you keep related things together in one document. It is like Russian nesting dolls, everything fits inside perfectly.

This tutorial turns embedding into a fun nesting game, super simple for beginners, but full of pro design patterns for experts.
We shall use our Hero Academy again.

Let’s start nesting!


๐Ÿ“‘ Table of Contents


Part 1: Why Embed? (The Superpower of One-Document Reads)

In SQL → You need multiple tables + JOINs → slow
In MongoDB → Put everything in one document → lightning fast!

Real-Life Examples:

  • A blog post + all its comments
  • A student + all his subjects & marks
  • An order + all items bought

Pros:

  • Atomic updates (everything changes together)
  • Super fast reads (one query gets everything)
  • No JOINs needed

Cons:

  • Document size limit: 16MB
  • Duplication if same data used in many places
  • Harder to query across many parents

Rule of Thumb: Embed when data is always used together and rarely changes independently.


Part 2: Creating Nested Data - Let’s Build Rich Hero Profiles.

use heroAcademy
db.heroes.insertOne({
  name: "Aarav",
  power: "Super Speed",
  level: 85,
  // Embedded Document (smaller box)
  profile: {
    age: 14,
    city: "Mumbai",
    school: "Superhero High"
  },
  // Array (treasure bag)
  skills: ["run", "jump", "quick thinking"],
  // Array of Embedded Documents!
  missions: [
    { name: "Save City", date: ISODate("2025-01-15"), reward: 100 },
    { name: "Stop Train", date: ISODate("2025-03-20"), reward: 150, completed: true }
  ],
  team: {
    name: "Alpha Squad",
    members: ["Priya", "Sanya", "Karan"],
    leader: "Captain Nova"
  }
})

Visual of Nested Document:
Embedded Document Structure
(One document with nested fields and arrays. )

Hero Document
└── {
    name: "Aarav"
    power: "Super Speed"
    level: 85

    profile: {
        age: 14
        city: "Mumbai"
        school: "Superhero High"
    }

    skills: [
        "run",
        "jump",
        "quick thinking"
    ]

    missions: [
        {
            name: "Save City"
            date: 2025-01-15
            reward: 100
        },
        {
            name: "Stop Train"
            date: 2025-03-20
            reward: 150
            completed: true
        }
    ]

    team: {
        name: "Alpha Squad"
        members: ["Priya", "Sanya", "Karan"]
        leader: "Captain Nova"
    }
}

Now the hero’s entire life is in one place!


Part 3: Querying Nested Data - Finding Treasures Inside Boxes

1. Dot Notation – Reach Inside Boxes

// Find heroes from Mumbai
db.heroes.find({ "profile.city": "Mumbai" })
// Find heroes with skill "jump"
db.heroes.find({ skills: "jump" })
// Find heroes who completed a mission
db.heroes.find({ "missions.completed": true })

Beginner Win: Just use dots like opening folders!

2. Exact Array Match

db.heroes.find({ skills: ["run", "jump", "quick thinking"] })

3. $elemMatch - Match Multiple Conditions in Same Array Item

db.heroes.find({
  missions: {
    $elemMatch: { reward: { $gt: 120 }, completed: true }
  }
})

4. $all - Must Have All These Skills

db.heroes.find({ skills: { $all: ["run", "jump"] } })

5. $size - Exact Number of Items

db.heroes.find({ skills: { $size: 3 } })

6. Array Index Position

db.heroes.find({ "skills.0": "run" })  // First skill is "run"

Performance & Indexing Tips for Nested Data

MongoDB automatically creates multikey indexes on arrays, but nested fields often need manual indexing for better performance.

You can speed up nested queries by adding indexes on fields like:

db.heroes.createIndex({ "missions.reward": 1 })
db.heroes.createIndex({ "profile.city": 1 })

Best Practices:

  • Index fields that you frequently query inside embedded documents.
  • Use compound indexes for combined queries (e.g., reward + completion status).
  • Avoid indexing very large arrays, they create heavy multikey indexes.
  • For deep or unpredictable structures, consider referencing instead of embedding.



Part 4: Updating Nested Data - The Magic Paintbrush

1. Update Embedded Field

Example:

db.heroes.updateOne(
  { name: "Aarav" },
  { $set: { "profile.age": 15, "profile.school": "Elite Academy" } }
)

2. Add to Array ($push)

db.heroes.updateOne(
  { name: "Aarav" },
  { $push: { skills: "lightning dash" } }
)

3. Add Multiple ($push + $each)

Example:

db.heroes.updateOne(
  { name: "Aarav" },
  {
    $push: {
      skills: { $each: ["fly", "laser eyes"] }
    }
  }
)

4. Remove from Array ($pull)

Example:

db.heroes.updateOne(
  { name: "Aarav" },
  { $pull: { skills: "jump" } }
)

5. Update Specific Array Element – Positional $ Operator

db.heroes.updateOne(
  { "missions.reward": 100 },
  { $set: { "missions.$.completed": true, "missions.$.reward": 200 } }
)

6. Update All Matching Array Elements ($[])

Example:

db.heroes.updateOne(
  { name: "Aarav" },
  { $inc: { "missions.$[].reward": 50 } }
)

7. Update Specific Element by Condition ($[identifier] + arrayFilters)

Example:

db.heroes.updateOne(
  { name: "Aarav" },
  { $set: { "missions.$[elem].completed": true } },
  { arrayFilters: [ { "elem.reward": { $gte: 150 } } ] }
)

→ Only missions with reward ≥ 150 get completed = true
Expert Power Move!


Part 5: Arrays of Embedded Documents - Real-World Power

Best for:

  • Blog post + comments
  • Order + line items
  • Student + list of subjects with marks

Example:

subjects: [
  { name: "Math", marks: 95, grade: "A+" },
  { name: "Science", marks: 88, grade: "A" }
]

Query:

db.students.find({ "subjects.name": "Math", "subjects.marks": { $gt: 90 } })

Update specific subject:

Example:

db.students.updateOne(
  { name: "Priya" },
  { $set: { "subjects.$.grade": "A++" } },
  { arrayFilters: [ { "subjects.name": "Math" } ] }
)

Part 6: When to Embed vs Reference? (The Golden Rule)

Embed vs Reference (Improved Guide)

Use Embedding When... Use Referencing When...
Data is always read together Child data is queried independently
One-to-few relationship (e.g., comments, profile details) One-to-many with many items (e.g., thousands of orders)
Child changes rarely and depends on parent Child changes frequently on its own
You need atomic updates Document could grow too large
Document stays well under the 16MB limit Data structure is unpredictable or unbounded

Pro Pattern: Hybrid, Embed frequently accessed data, reference rarely changed or huge data.

Example: Embed address in user (changes rarely), reference orders (many, queried separately).


Part 7: Mini Project - Build a Complete Hero Card!

db.heroes.insertOne({
  name: "YouTheReader",
  power: "Learning MongoDB",
  level: 100,
  profile: {
    age: "Ageless",
    location: "Everywhere"
  },
  achievements: [
    "Finished Embedding Tutorial",
    "Understood $elemMatch",
    "Used Positional Operator"
  ],
  superMoves: [
    { name: "Query Storm", power: 999, cooldown: 0 },
    { name: "Index Blitz", power: 1000, cooldown: 5 }
  ]
})

Now try these queries:

db.heroes.find(
  { "superMoves.power": { $gt: 900 } },
  { name: 1, "superMoves.$": 1 }   // Only show matching array elements!
)

Part 8: Tips for All Levels

For Students & Beginners

  • Start with simple nesting: one embedded object + one array
  • Use Compass → you can click into nested fields!
  • Practice with your own “Game Character” document

For Medium Learners

  • Always use $elemMatch when multiple conditions on same array element
  • Use positional $[] for updating all matching array items
  • Remember document 16MB limit!

For Experts

  • Use multikey indexes automatically created on arrays
  • For large arrays > 100 items → consider child collection
  • Use $filter in aggregation to process arrays:
{
  $project: {
    highRewardMissions: {
      $filter: {
        input: "$missions",
        as: "m",
        cond: { $gte: ["$$m.reward", 150] }
      }
    }
  }
}

Schema validation for nested data:

validator: {
  $jsonSchema: {
    properties: {
      profile: { bsonType: "object" },
      skills: { bsonType: "array", items: { bsonType: "string" } }
    }
  }
}



Part 9: Cheat Sheet (Print & Stick!)

TaskCommand Example
Query nested field{ "profile.city": "Mumbai" }
Query array item{ skills: "fly" }
Exact array{ skills: ["a", "b"] }
Multiple array conditions{ array: { $elemMatch: { a: 1, b: 2 } } }
Update nested{ $set: { "profile.age": 16 } }
Add to array{ $push: { skills: "new" } }
Remove from array{ $pull: { skills: "old" } }
Update matched array element"missions.$" with filter
Update all array elements"missions.$[]"

⚡ Quick Summary

  • MongoDB embedding lets you store related data inside a single document (like Russian nesting dolls).
  • Use embedded documents for structured nested data.
  • Use arrays for multiple values or lists of objects.
  • Dot notation ("profile.city": "Mumbai") makes nested queries easy.
  • Array operators such as $elemMatch, $all, $size, $push, $pull, and positional $ give powerful control.
  • Embed when data is small, always read together, and rarely updated independently.
  • Reference when data is large, independently updated, or frequently queried alone.

๐Ÿงช Test Yourself

Try these challenges to test your understanding:

  1. Create a student document containing:
    • an embedded profile object
    • a subjects array (each subject is an embedded document)
    • a hobbies array
  2. Query students who have a subject named "Math" with marks greater than 80.
  3. Update all subject marks by +5 using the $[] operator.
  4. Remove the hobby "gaming" from the hobbies array.
  5. Add two new subjects to the subjects array using $push with $each.

If you can solve these, you're well on your way to mastering MongoDB nesting!


๐Ÿ’ก Common Mistakes

  • Not using $elemMatch when applying multiple conditions to a single array element.
  • Updating arrays without positional operators such as $, $[], or $[identifier].
  • Embedding huge arrays that may grow into hundreds or thousands of items.
  • Duplicating data by embedding objects that should be referenced instead.
  • Ignoring the 16MB document limit, especially when storing logs or long lists.

❗ Things to Avoid When Embedding

  • Embedding large collections such as thousands of comments.
  • Embedding data that changes frequently on its own.
  • Embedding child items you often query independently.
  • Embedding arrays or structures that can grow unpredictably.
  • Embedding complex structures that rely on dynamic keys.

Golden Rule:
Embed when data is small and tightly related.
Reference when data is large, independent, or often queried separately.


Final Words

You’re a Nesting Master.

You just learned:

  • How to build rich, nested documents
  • Query with dot notation, $elemMatch, $all
  • Update with $push, positional operators, arrayFilters
  • When to embed vs reference (the most important design decision!)

Your Nesting Mission:
Create a document about your favorite game character with:

  • Embedded stats object
  • inventory array
  • quests array of objects

You’re now a Certified MongoDB Russian Doll Architect.

Resources:
Embedded vs Reference Docs (official MongoDB guide)
MongoDB Array & Update Operators – Positional Operator $
MongoDB Data Modeling & Embedding Best Practices

Array Operators
Positional Operator
Keep nesting like a pro.

Creating Your First MongoDB Database and Collection (Step-by-Step Tutorial)



Creating Your First MongoDB Database and Collection

A Super Fun, Step-by-Step Adventure for Beginner to Expert Level


What is MongoDB?
MongoDB is a popular NoSQL database that stores data in flexible, JSON-like documents instead of rigid tables used in SQL databases. This makes it perfect for modern apps, projects, and learning how data really works!

Imagine you’re opening a magic toy box where you can store toys, games, books, and secret treasures — all in one place! In MongoDB, a database is your toy box, and a collection is a shelf inside it. This tutorial teaches you how to create your first database and collection using simple words, fun examples, and real tools, perfect for students, but packed with pro tips for experienced learners.

We’ll use:

  • mongosh (the modern MongoDB shell)
  • MongoDB Compass (a click-and-play GUI)
  • Real images from MongoDB
  • A fun "Pet Shop" project

Level: Beginners to Pro


Let’s open the toy box!

Part 1: What Are Databases and Collections?

TermReal-Life ExampleMongoDB Meaning
DatabaseA big toy boxA container for all your data
CollectionA shelf inside the toy boxA group of similar items (documents)

Fun Fact: You don’t need to “create” a database first! MongoDB makes it automatically when you add data!


Part 2: Method 1- Using mongosh (The Command Way)

Step 1: Open mongosh

After installing MongoDB (see our first tutorial), open your terminal (Linux/macOS) or Command Prompt/PowerShell (Windows).

Type:

mongosh

You’ll see:

test>

Beginner Tip: The > is your magic wand. Type spells (commands) here!

Step 2: Create Your First Database – petshop

use petshop

What happens?
MongoDB switches to (or creates) a database called petshop.
But it’s invisible until you add data!
Like: Opening a new toy box labeled “Pet Shop” , but it’s empty!

Step 3: Create Your First Collection – animals

db.animals.insertOne({
  name: "Buddy",
  species: "Dog",
  age: 3,
  color: "Golden",
  loves: ["balls", "walks", "treats"]
})

Output:

{
  acknowledged: true,
  insertedId: ObjectId("671a5f2c8e4b2c1f9d5e7a3d")
}

Magic Moment!
petshop database is now created
animals collection is now created
Buddy the dog is now stored
Beginner Example: You just put the first toy (Buddy) on the “Animals” shelf!

Step 4: Add More Pets!

db.animals.insertMany([
  {
    name: "Whiskers",
    species: "Cat",
    age: 2,
    color: "Gray",
    loves: ["napping", "laser pointer"]
  },
  {
    name: "Goldie",
    species: "Fish",
    age: 1,
    color: "Orange",
    loves: ["swimming", "bubbles"]
  }
])

Pro Tip: Use insertMany() for bulk add faster and cleaner!

Step 5: See Your Data!

db.animals.find()

Output:

{ "_id": ObjectId("..."), "name": "Buddy", ... }
{ "_id": ObjectId("..."), "name": "Whiskers", ... }
{ "_id": ObjectId("..."), "name": "Goldie", ... }

Pretty View:

db.animals.find().pretty()

Beginner Win: You just opened the toy box and saw all pets!

Step 6: Check What’s Created

show dbs

→ Shows all databases (now includes petshop)

show collections

→ Shows animals

db.animals.countDocuments()

→ Returns 3 (total pets)



Part 3: Method 2 – Using MongoDB Compass (The Click Way)

Step 1: Open Compass

Download: mongodb.com/compass
Open the app.

Step 2: Connect to Your Local MongoDB

Connection: mongodb://localhost:27017
Click Connect

Step 3: Create Database & Collection Visually

Click "Create Database"
Name: petshop
Collection: animals
Click Create

Step 4: Add a Pet with Clicks!

Click on animals collection
Click "Add Data" → "Insert Document"
Paste or type:

{
  "name": "Fluffy",
  "species": "Rabbit",
  "age": 1,
  "color": "White",
  "loves": ["carrots", "hopping"]
}

Click Insert
Beginner Magic: No typing commands! Just click and add!

Step 5: See Your Pet Shop!

You’ll see all pets in a beautiful table:
Expert Feature: Click column headers to sort, or use filter bar:

{ "species": "Dog" }


Part 4: Understanding the Magic Behind the Scenes

ActionWhat MongoDB Does Automatically
use petshopSwitches context (no file created yet)
insertOne()Creates DB + Collection + Document
show dbsLists only DBs with data
No CREATE DATABASE command needed!


Part 5: Mini Project – Build a Full Pet Shop!

1. Add More Collections

// Toys collection
db.toys.insertOne({
  name: "Squeaky Ball",
  for: "Dog",
  price: 5.99,
  inStock: true
})

// Owners collection
db.owners.insertOne({
  name: "Aarav",
  phone: "9876543210",
  pets: ["Buddy", "Whiskers"]
})

2. Smart Queries

// Find dogs older than 2
db.animals.find({ species: "Dog", age: { $gt: 2 } })

// Find pets that love "treats"
db.animals.find({ loves: "treats" })

// Count cats
db.animals.countDocuments({ species: "Cat" })

3. Update a Pet

db.animals.updateOne(
  { name: "Buddy" },
  { $set: { age: 4, vaccinated: true } }
)

4. Delete a Toy (Carefully!)

db.toys.deleteOne({ name: "Squeaky Ball" })


Part 6: Pro Tips for All Levels

For students & Beginners

  • Use Compass to avoid typos
  • Make a "Game Collection" with characters
  • Always use .pretty() in mongosh

For Medium Learners

db.animals.createIndex({ species: 1 })
db.createCollection("animals", {
  validator: {
    $jsonSchema: {
      required: ["name", "species"],
      properties: {
        age: { bsonType: "int", minimum: 0 }
      }
    }
  }
})

Note: In modern versions of MongoDB, "bsonType": "int" can also be written as "bsonType": "number" depending on your environment and data type. Both work correctly as long as the field value matches the expected numeric format.


For Experts

db.createCollection("logs", { capped: true, size: 100000 })

db.animals.createIndex({ name: "text" })
db.animals.find({ $text: { $search: "Buddy" } })

// Use Atlas for cloud (no install!)
cloud.mongodb.com


Part 7: Cheat Sheet (Print & Stick!)

CommandWhat It Does
mongoshOpen shell
use dbnameSwitch/create database
db.collection.insertOne({})Add one item
db.collection.insertMany([])Add many items
db.collection.find()Show all
db.collection.find().pretty()Show nicely
show dbsList databases
show collectionsList shelves
db.collection.drop()Delete shelf
db.dropDatabase()Delete entire toy box


Part 8: Common Mistakes & Fixes

MistakeFix
Typing create database petshopNot needed! Just use petshop
Forgetting quotes in stringsUse "name": "Buddy"
Using wrong collection nameCheck with show collections
Data not showing in show dbsYou must insert data first!


๐Ÿ’ก Quick Quiz & Challenge

  1. What command automatically creates both a database and collection in MongoDB?
  2. How do you display all documents in a collection neatly?
  3. Which MongoDB GUI lets you create databases with just clicks?

Bonus Challenge:
Try adding an owners-to-pets relationship using ObjectId references. Here’s an example to get you started:

// Step 1: Insert pets
db.animals.insertOne({
  name: "Buddy",
  species: "Dog"
})

// Step 2: Get Buddy's _id
var buddyId = db.animals.findOne({ name: "Buddy" })._id

// Step 3: Create an owner referencing Buddy
db.owners.insertOne({
  name: "Aarav",
  pets: [buddyId]
})

// Step 4: Verify relationship
db.owners.aggregate([
  {
    $lookup: {
      from: "animals",
      localField: "pets",
      foreignField: "_id",
      as: "petDetails"
    }
  }
])

๐ŸŽ‰ Pro Tip: This approach helps you model real relationships between collections just like linking tables in SQL, but more flexible!



Final Words

You Did It!


You just:
  • Created your first database (petshop)
  • Made a collection (animals)
  • Added, viewed, and managed real data
  • Used both command line and GUI

Fun Learned: Infinite

Your Next Mission:

use myWorld
db.heroes.insertOne({
  name: "You",
  power: "MongoDB Master",
  level: "Expert"
})

You’re now a Certified MongoDB Creator!



๐Ÿ‘‰ Next Tutorial: Level Up Your MongoDB Skills

Now that you’ve mastered databases and collections, take your next step in learning MongoDB queries and relationships!

๐Ÿš€ Next: Master MongoDB Queries and Relationships

Coming soon: Learn how to search, filter, and connect data across collections like a pro!

Resources:

Keep building magic toy boxes! ๐Ÿงธ✨

Data Modeling Best Practices for SQL and NoSQL Databases: A Beginner’s Guide

๐Ÿ”ท Part 14: Data Modeling Best Practices – Design Efficient Database Schemas


๐Ÿ“ Introduction

Data modeling is the blueprint of your database. It determines how data is organized, stored, and accessed — directly impacting performance, scalability, and maintenance.

This part covers core best practices for data modeling in both SQL (relational) and NoSQL (document, key-value) databases, helping you design robust schemas.


๐Ÿ”ธ 1. Understand Your Data and Use Cases

  • Analyze the data you need to store.

  • Understand how applications will use the data.

  • Identify relationships and access patterns.


๐Ÿ”น 2. Normalize Data in SQL

  • Apply normal forms (1NF, 2NF, 3NF) to reduce redundancy.

  • Use primary keys to uniquely identify rows.

  • Define foreign keys to enforce relationships.


๐Ÿ”ธ 3. Denormalize When Appropriate

  • Denormalization stores redundant data for faster reads.

  • Useful in read-heavy applications to reduce joins.

  • Balance between normalization and performance.


๐Ÿ”น 4. Design Schema for NoSQL Based on Queries

  • Model data to match how you query it, not just how it’s related.

  • Embed related data within documents when needed.

  • Use references if data is large or shared.

Schema Examples

๐Ÿ“ฆ SQL Example – Customer Table


CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY,
    Name VARCHAR(100),
    Email VARCHAR(100),
    CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

๐Ÿงพ NoSQL Example – Customer Document (MongoDB)


{
  "customer_id": 123,
  "name": "Chritiano Ronaldo",
  "email": "ronaldo@example.com",
  "created_at": "2025-08-18T10:30:00Z"
}


๐Ÿ”ธ 5. Use Consistent Naming Conventions

  • Use clear, meaningful table and column names.

  • Stick to one naming style (snake_case, camelCase).

  • Avoid reserved keywords and spaces.


๐Ÿ”น 6. Plan for Scalability

  • Design schemas that accommodate growth.

  • Use partitioning/sharding strategies early if needed.

  • Avoid complex joins in NoSQL by thoughtful data embedding.


๐Ÿ“ Summary

Aspect SQL Best Practices NoSQL Best Practices
Data Organization Normalization + Foreign Keys Embed or Reference based on queries
Redundancy Minimize via normalization Controlled denormalization for performance
Schema Flexibility Strict, predefined schema Flexible, schema-less or dynamic schema
Naming Consistent, meaningful Same
Scalability Partitioning, indexing Sharding, replication

New here? Start with Part 13: Database Performance Tuning.

Next Steps

In Part 15, we’ll cover Advanced Query Techniques — writing complex queries and aggregations in SQL and NoSQL.


๐Ÿ’ฌ Join the Conversation

Have data modeling tips of your own? Leave a comment below! ๐Ÿ”ง


Practice Assignment: SQL JOINs vs MongoDB Referencing

๐Ÿงช Practice Assignment: SQL JOINs vs MongoDB Referencing


Here's a clear and practical assignment to help readers compare SQL JOINs with MongoDB referencing. This exercise is designed to reinforce how both systems manage relationships through hands-on tasks.


๐ŸŽฏ Objective:

Understand how to build and query related data using:

  • SQL with JOINs

  • MongoDB with manual referencing


๐Ÿ“š Scenario:

You’re building a simple Library System with:

  • A list of Authors

  • A list of Books written by those authors

Each book belongs to one author, and each author can write multiple books (One-to-Many relationship).


๐Ÿ”น Part A: SQL – Using Foreign Keys & JOINs


Step 1: Create Tables

CREATE TABLE Authors (
  AuthorID INT PRIMARY KEY,
  Name VARCHAR(100)
);

CREATE TABLE Books (
  BookID INT PRIMARY KEY,
  Title VARCHAR(150),
  AuthorID INT,
  FOREIGN KEY (AuthorID) REFERENCES Authors(AuthorID)
);

Step 2: Insert Data

INSERT INTO Authors (AuthorID, Name) VALUES
(1, 'George Orwell'),
(2, 'J.K. Rowling');

INSERT INTO Books (BookID, Title, AuthorID) VALUES
(101, '1984', 1),
(102, 'Animal Farm', 1),
(103, 'Harry Potter', 2);

Step 3: Write a JOIN Query

Write a SQL query to display all book titles along with their author names.

Example:

SELECT Books.Title, Authors.Name
FROM Books
JOIN Authors ON Books.AuthorID = Authors.AuthorID;

๐Ÿ”น Part B: MongoDB – Manual Referencing


Step 1: Insert Documents

Authors Collection:

db.authors.insertMany([
  { _id: 1, name: "George Orwell" },
  { _id: 2, name: "J.K. Rowling" }
]);

Books Collection:

db.books.insertMany([
  { title: "1984", author_id: 1 },
  { title: "Animal Farm", author_id: 1 },
  { title: "Harry Potter", author_id: 2 }
]);

Step 2: Query to Simulate a JOIN

Write MongoDB queries to show book titles and their author names:

Step 1: Get author document

const author = db.authors.findOne({ name: "George Orwell" });

Step 2: Find all books by that author

db.books.find({ author_id: author._id });

๐Ÿ”ธ Optional Challenge: Try Embedding in MongoDB

Instead of referencing, restructure books with embedded author info:

db.books.insertOne({
  title: "1984",
  author: {
    id: 1,
    name: "George Orwell"
  }
});

Then query:

db.books.find({ "author.name": "George Orwell" });

๐Ÿง  Reflection Questions

  1. Which method (JOIN or referencing) felt more intuitive to you?

  2. How does MongoDB referencing differ from SQL JOINs?

  3. What trade-offs do you notice in terms of query performance or complexity?


  • Click Next to view solution with expected outputs


Feel free to share your thoughts in the comments!


Normalization vs Denormalization in Databases: SQL vs NoSQL Explained Simply


๐Ÿ”ท Part 7: Normalization vs Denormalization – Understanding Data Structure in SQL and NoSQL


This part will help beginners and pros understand how data is structured differently in these databases(SQL and NoSQL) and impacts performance, flexibility, and maintenance.


๐Ÿ“ Introduction

Data organization is a cornerstone of database efficiency in both SQL and NoSQL systems. Two essential techniques for structuring data are Normalization and Denormalization. Techniques like normalization (used in relational databases) and denormalization (common in document-based NoSQL databases like MongoDB) affect performance, scalability, and data integrity.

  • Normalization is commonly used in SQL databases to reduce data redundancy by organizing data into related tables.

  • Denormalization is often preferred in NoSQL databases like MongoDB, where embedding data improves read performance at the cost of some duplication.

In this post, we’ll break down these concepts, explain their pros and cons, and provide examples to make it crystal clear.


๐Ÿ”ธ 1. What is Normalization in SQL Databases?

Normalization is the process of structuring a relational database so that:

  • Data is stored in multiple related tables

  • Each table contains data about one type of entity

  • Redundancy is minimized

  • Integrity and consistency are ensured


๐Ÿ“ Example: Students and Courses

  • Students Table: Stores student details

  • Courses Table: Stores course details

  • Enrollments Table: Links students to courses (many-to-many relationship)

This normalized structure in SQL avoids repeating course information for every student, ensuring data integrity and reducing redundancy.


๐Ÿ”ธ 2. What is Denormalization?

Denormalization is the process of intentionally introducing redundancy by:

  • Combining related data into single documents or tables

  • Embedding data to optimize read performance

  • Simplifying queries by reducing joins


๐Ÿ“ Example: MongoDB Student Document

Here is a denormalized NoSQL document structure example using MongoDB.

Instead of separate collections, a student document contains embedded courses and marks:

{
  "student_id": 101,
  "name": "Aisha Khan",
  "class": "10A",
  "courses": [
    { "course_id": 301, "title": "Math", "score": 85 },
    { "course_id": 302, "title": "Science", "score": 90 }
  ]
}


๐Ÿ”ธ 3. Pros and Cons

Aspect Normalization (SQL) Denormalization (NoSQL)
Data Redundancy Low High (intentional duplication)
Query Complexity More complex (joins needed) Simple (embedded data, fewer joins)
Data Consistency Easier to maintain More challenging to keep consistent
Performance Good for writes, complex reads Optimized for reads, slower writes
Flexibility Schema-based, less flexible Schema-less, highly flexible

๐Ÿ”ธ 4. When to Use Which?

  • Use Normalization (SQL):
    When data integrity is crucial, and you expect complex queries involving relationships.

  • Use Denormalization (NoSQL):
    When performance on reads is critical, and you want flexible, evolving schemas.


๐Ÿง  Summary

Understanding the difference between normalization in SQL and denormalization in NoSQL helps you choose the right database structure and design models that balance performance and consistency for your project. Choosing between normalization and denormalization depends on your project needs—whether you prioritize performance or data integrity.

If you have not gone through previous tutorial read: Part-6: CRUD Operations in SQL vs NoSQL – A Beginner's Guide


Task for you:

    Try normalizing a sample dataset and share your experience.

    Leave a comment below if you have used either in your projects.



✅ What’s Next?

In Part 8, we shall explore Indexing and Query Optimization to speed up your database performance.



  • Practice exercises for normalization and denormalization


Featured Post

Master MongoDB with Node.js Using Mongoose: Complete Guide

Working with MongoDB from Node.js using Mongoose Your Magical Mongoose Pet That Makes MongoDB Super Easy For Beginner to Expert Level ...

Popular Posts