Embedded documents in MongoDB: A practical guide (with examples)

Updated: February 3, 2024 By: Guest Contributor Post a comment

Introduction

MongoDB, a leading NoSQL database, is famous for its flexible schema, scalability, and performance. One of its many features is the ability to store embedded documents, which are essentially documents nested within other documents. Such a structure is used to represent relationships between data by embedding related data directly within a document. In this thorough guide, we’ll take a closer look at embedded documents in MongoDB with practical examples, helping you to understand when and how to use them effectively.

Understanding Embedded Documents

In MongoDB, embedding documents is a common practice to model related pieces of information. An embedded document is stored as a subdocument inside a field of a parent document. This creates a hierarchical data structure within a single MongoDB document. Let’s start with a basic example:

// Sample MongoDB document with an embedded document
{
  _id: ObjectId('507f191e810c19729de860ea'),
  product_name: 'Coffee Mug',
  manufacturer: {
    name: 'Good Coffee Inc.',
    location: 'Portland, Oregon'
  }
}

This document has an embedded document within the ‘manufacturer’ field, containing name and location information.

Working with Embedded Documents

Let’s proceed with some CRUD (Create, Read, Update, Delete) operations involving embedded documents in MongoDB.

Inserting Documents with Embedded Data

Suppose we’re working on an e-commerce database. First, we need to insert products with details about the manufacturer embedded within each product document:

db.products.insertOne({
  product_name: 'Coffee Mug',
  manufacturer: {
    name: 'Good Coffee Inc.',
    location: 'Portland, Oregon'
  }
});

Of course, you can insert multiply objects:

db.products.insertMany([
    {
    product_name: 'Coffee Mug',
    manufacturer: {
        name: 'Good Coffee Inc.',
        location: 'Portland, Oregon'
    }
    },
    {
    product_name: 'Tea Cup',
    manufacturer: {
        name: 'Good Tea Inc.',
        location: 'Seattle, Washington'
    }
    }
]);

In these commands, a new product with an embedded ‘manufacturer’ document is added to the ‘products’ collection.

Reading Documents with Embedded Data

To find all products made by ‘Good Coffee Inc.:

db.products.find({'manufacturer.name': 'Good Coffee Inc.'});

This query will return all products wherein the embedded ‘manufacturer’ document has a ‘name’ field equal to ‘Good Coffee Inc.’:

In the following example we query those documents ()nested by at least one level deep inside the document):

db.products.find({'manufacturer.name': { $exists:true}});

Updating Embedded Documents

Let’s say ‘Good Coffee Inc.’ changes its location and you want to update your database. You can update the location field of the embedded ‘manufacturer’ document with the following command:

db.products.updateMany(
  {'manufacturer.name': 'Good Coffee Inc.'},
  { $set: {'manufacturer.location': 'Eugene, Oregon'} }
);

This will modify the location for all products associated with ‘Good Coffee Inc.’.

Deleting Embedded Documents or Fields

If you decide to remove the manufacturer data entirely or just a specific field like the location, you can perform the following operation:

// To remove a specific field
db.products.updateMany({},
  { $unset: {'manufacturer.location': ''} }
);

// To remove the entire embedded document
db.products.updateMany({},
  { $unset: {'manufacturer': ''} }
);

It’s important to note that ‘updateMany’ without a query selector will affect all documents in the collection.

Best Practices for Using Embedded Documents

The decision to use embedded documents should be informed by the benefits and limitations of this approach.

  • Advantages of Embedded Documents: they lend themselves to atomic operations, reduce the need for separate queries, and avoid joins which are not natively supported in MongoDB.
  • Limitations: Embedded documents can contribute to document growth that may lead to performance issues. They are also subject to the BSON document size limit, currently 16MB.
  • Denormalization: When data is duplicated in multiple documents to avoid joins, ensures data consistency carefully.

Advanced Querying and Indexing

To work more efficiently with embedded documents, it’s essential to utilize indexing and advanced querying techniques. Let’s look at how to create an index on a field within an embedded document:

db.products.createIndex({'manufacturer.name': 1});

By indexing the ‘name’ field of the ‘manufacturer’ embedded document, we improve the performance of queries filtering by this field.

Conclusion

This guide showcased the practical applications of embedded documents in MongoDB, offering insights into their uses and operations. Employing embedded documents effectively can streamline your data structure and improve access patterns within your applications. Always weigh the trade-offs and align your database design with the specific requirements of your project.