Paramclasses Academy - Blog

Tutorials Details

←
Post 16 of 35
→

MongoDB Data Modeling: Embedded Documents vs References

MongoDB Data Modeling: Embedded Documents vs References

November 5, 2026

MongoDB Data Modeling: Embedded Documents vs References

Welcome to Param Classes!

When designing a MongoDB database, one of the most important decisions is how to organize and store related data.

Unlike traditional relational databases, MongoDB stores data in flexible BSON documents. Related information can be stored inside the same document or in separate documents connected through references.

MongoDB provides two common approaches for managing related data:

  • Embedded Documents – Store related information inside a single document.

  • References – Store related information in separate documents and connect them using unique identifiers.

In this tutorial, you will learn both approaches with practical examples, advantages, disadvantages and real-world database design scenarios.

✦ 1. What Is Data Modeling in MongoDB?

Data modeling is the process of deciding how information should be organized and stored in a database.

A good MongoDB data model helps applications retrieve information efficiently, maintain data consistency and manage relationships between different records.

For example, consider an online shopping application containing:

  • Customers

  • Products

  • Orders

  • Payments

  • Addresses

We need to decide whether related information should be stored together or separately.

This is where embedded documents and references become important.

✦ 2. What Are Embedded Documents in MongoDB?

Embedded documents are documents stored inside another document.

Instead of creating separate collections for related information, we can store that information together within a single document.

This approach is useful when related data is frequently accessed together.

Example:

Suppose we want to store student information along with their address.

db.students.insertOne({
    name: "Rahul",
    age: 22,
    course: "MongoDB",
    address: {
        city: "Raipur",
        state: "Chhattisgarh",
        country: "India",
        pincode: 492001
    }
})

Here:

  • name, age and course are student fields.

  • address is an embedded document.

  • city, state, country and pincode are stored inside the address document.

To retrieve the student record:

db.students.find()

To retrieve only the student's name and city:

db.students.find(
    {},
    {
        name: 1,
        "address.city": 1,
        _id: 0
    }
)

MongoDB allows us to access embedded fields using dot notation.

Advantages of Embedded Documents

  1. Related information is stored in one document.

  2. Data can be retrieved using a single query.

  3. No separate lookup is required to read embedded information.

  4. Related changes can often be performed atomically within one document.

  5. It can improve read performance when related data is frequently accessed together.

Disadvantages of Embedded Documents

  1. Documents can become very large.

  2. Repeated information may create data duplication.

  3. Frequently changing embedded information can be difficult to manage.

  4. Unbounded arrays can cause document growth problems.

  5. MongoDB documents have a maximum BSON size of 16 MB.

✦ 3. What Are References in MongoDB?

References are used to connect documents stored in different collections.

Instead of embedding complete information inside another document, we store the unique _id of the related document.

This approach is useful when data is shared between multiple records or when related information grows independently.

Example:

First, create a students collection:

db.students.insertOne({
    _id: 101,
    name: "Rahul",
    age: 22,
    course: "MongoDB"
})

Now create a separate addresses collection:

db.addresses.insertOne({
    studentId: 101,
    city: "Raipur",
    state: "Chhattisgarh",
    country: "India"
})

Here:

  • Student information is stored in the students collection.

  • Address information is stored in the addresses collection.

  • studentId connects the address record with the student record.

To retrieve the student:

db.students.findOne({
    _id: 101
})

To retrieve the related address:

db.addresses.findOne({
    studentId: 101
})

MongoDB does not automatically join referenced documents in a normal find() query. We retrieve related information through separate queries or aggregation using $lookup.

✦ 4. How to Use References with $lookup?

MongoDB provides the $lookup aggregation stage to combine related information from different collections.

Let's retrieve student details along with their addresses.

Example:

db.students.aggregate([
    {
        $lookup: {
            from: "addresses",
            localField: "_id",
            foreignField: "studentId",
            as: "studentAddress"
        }
    }
])

Here:

  • from specifies the collection to connect.

  • localField specifies the field from the current collection.

  • foreignField specifies the matching field in the other collection.

  • as specifies the name of the resulting array.

The result contains student information along with matching address information inside studentAddress.

Important: $lookup returns matching documents in an array. If no matching address exists, the array will be empty.

✦ 5. Embedded Documents vs References: Key Differences

Both approaches are useful, but they serve different database requirements.

Feature Embedded Documents References
Storage Same document Separate documents
Relationship Nested structure ID-based connection
Data Retrieval Usually one query Separate queries or $lookup
Performance Efficient for related reads Depends on retrieval pattern
Data Duplication May occur Can reduce duplication
Document Size Can grow significantly Data remains separate
Best Use Closely related data Shared or independently managed data

✦ 6. When Should You Use Embedded Documents?

Embedded documents are a good choice when related information is usually accessed together.

Common use cases:

  1. Student details with address.

  2. User profiles with contact information.

  3. Product details with specifications.

  4. Blog posts with a small number of comments.

  5. Order details with shipping information.

Example: User Profile

db.users.insertOne({
    name: "Amit",
    email: "amit@example.com",
    profile: {
        phone: "9876543210",
        city: "Raipur",
        state: "Chhattisgarh"
    }
})

Here, profile information is embedded inside the user document.

This makes it convenient to retrieve user and profile information together.

✦ 7. When Should You Use References?

References are useful when related information needs to be managed separately or is shared across multiple documents.

Common use cases:

  1. Customers and their orders.

  2. Products and categories.

  3. Students and course records.

  4. Users and their transactions.

  5. Authors and their published articles.

Example: Customer and Orders

First, insert a customer:

db.customers.insertOne({
    _id: 201,
    name: "Priya",
    email: "priya@example.com"
})

Now insert orders separately:

db.orders.insertMany([
    {
        orderId: 1001,
        customerId: 201,
        product: "Laptop",
        amount: 55000
    },
    {
        orderId: 1002,
        customerId: 201,
        product: "Mouse",
        amount: 800
    }
])

Here:

  • Customer information is stored separately.

  • Multiple orders are connected using customerId.

  • We can add more orders without continuously expanding the customer document.

This approach is useful for applications where customers can place many orders.

✦ 8. One-to-One, One-to-Many and Many-to-Many Relationships

MongoDB supports different types of relationships through embedded documents and references.

A. One-to-One Relationship

One record is associated with one related record.

Example: One user has one profile.

An embedded approach:

db.users.insertOne({
    name: "Rahul",
    profile: {
        age: 25,
        city: "Raipur"
    }
})

B. One-to-Many Relationship

One record is associated with multiple related records.

Example: One customer can have multiple orders.

Using references:

db.orders.insertMany([
    {
        customerId: 201,
        product: "Laptop"
    },
    {
        customerId: 201,
        product: "Keyboard"
    },
    {
        customerId: 201,
        product: "Mouse"
    }
])

C. Many-to-Many Relationship

Multiple records can be associated with multiple other records.

Example: Students can enroll in multiple courses, and each course can have multiple students.

Using references:

db.students.insertMany([
    {
        _id: 301,
        name: "Aman"
    },
    {
        _id: 302,
        name: "Riya"
    }
])

Create a courses collection:

db.courses.insertMany([
    {
        _id: 401,
        courseName: "MongoDB",
        studentIds: [301, 302]
    },
    {
        _id: 402,
        courseName: "Java",
        studentIds: [301]
    }
])

Here:

  • Aman is enrolled in MongoDB and Java.

  • Riya is enrolled in MongoDB.

  • Course documents store references to students.

For larger or more complex many-to-many relationships, a separate linking collection can also be used.

✦ 9. Real-World Example: Online Shopping Database

Let's understand how both approaches can be used in an online shopping application.

An online shopping system may contain:

  • Customers

  • Products

  • Orders

  • Addresses

A possible database structure is:

Customers Collection:

{
    _id: 501,
    name: "Rahul",
    email: "rahul@example.com",
    address: {
        city: "Raipur",
        state: "Chhattisgarh"
    }
}

Products Collection:

{
    _id: 601,
    productName: "Laptop",
    price: 55000,
    brand: "Dell"
}

Orders Collection:

{
    _id: 701,
    customerId: 501,
    products: [
        {
            productId: 601,
            quantity: 1,
            price: 55000
        }
    ],
    totalAmount: 55000,
    status: "Delivered"
}

In this example:

  • Customer address is embedded inside the customer document.

  • Product information is maintained in a separate collection.

  • Orders reference the customer using customerId.

  • Order items store product references and the purchase price.

This design combines embedded documents and references according to the application's requirements.

Storing the purchase price in the order also preserves the price paid at the time of purchase, even if the product's current price changes later.

✦ 10. Important Best Practices for MongoDB Data Modeling

Follow these practices when designing a MongoDB database:

  1. Design your schema according to application query patterns.

  2. Use embedded documents for closely related information.

  3. Use references for shared or independently managed data.

  4. Avoid unlimited growth of embedded arrays.

  5. Consider the 16 MB BSON document size limit.

  6. Avoid unnecessary data duplication.

  7. Use indexes on frequently queried reference fields.

  8. Consider read and write performance before choosing a relationship structure.

  9. Use $lookup when aggregation-based joining is required.

  10. Choose a structure that supports future application growth.

✦ 11. Practical Exercise

Now practice embedded documents and references yourself.

Task 1: Create a users collection

db.users.insertOne({
    name: "Aman",
    email: "aman@example.com",
    address: {
        city: "Raipur",
        state: "Chhattisgarh"
    }
})

Task 2: Create a products collection

db.products.insertMany([
    {
        _id: 801,
        name: "Laptop",
        price: 50000
    },
    {
        _id: 802,
        name: "Keyboard",
        price: 1500
    }
])

Task 3: Create an orders collection

db.orders.insertOne({
    customerId: 1,
    products: [
        {
            productId: 801,
            quantity: 1
        },
        {
            productId: 802,
            quantity: 2
        }
    ],
    status: "Pending"
})

Practice Questions:

  1. What is an embedded document in MongoDB?

  2. What is a reference in MongoDB?

  3. Create a user document with embedded address details.

  4. Create separate customer and orders collections.

  5. Explain how $lookup connects two collections.

  6. Identify the best approach for a customer with multiple orders.

  7. Explain the difference between one-to-one and one-to-many relationships.

Try completing these exercises using MongoDB Shell (mongosh).

✦ 12. Conclusion

In this tutorial, we learned MongoDB data modeling using embedded documents and references.

We covered their structure, differences, advantages, disadvantages and practical examples.

Remember:

  • Embedded documents store related information inside one document.

  • References connect separate documents using unique identifiers.

  • $lookup helps retrieve related information from different collections.

  • Embedded documents are useful for closely related data.

  • References are useful for shared and independently managed data.

Choosing the right data model is important for building scalable, efficient and well-organized MongoDB applications.

Keep learning with Param Classes and continue improving your MongoDB database development skills.

←
Post 16 of 35
→