Updating Nested Fields and Embedded Documents

MongoDB lets you update nested fields using dot notation. Choosing the correct update expression is important because replacing an entire embedded document can unintentionally remove sibling fields.

Update one nested field

Suppose the document is:

{
  name: "Arun",
  address: {
    city: "Chennai",
    country: "India",
    postalCode: "600001"
  }
}

To change only the city:

db.users.updateOne(
  { name: "Arun" },
  { $set: { "address.city": "Bengaluru" } }
);

The country and postalCode fields remain unchanged.

Replace an embedded document value

db.users.updateOne(
  { name: "Arun" },
  {
    $set: {
      address: {
        city: "Bengaluru"
      }
    }
  }
);

This replaces the value of the address field with a document containing only city. The previous country and postalCode fields are removed from that embedded document.

This is a frequent source of accidental data loss.

Update multiple nested fields

db.users.updateOne(
  { name: "Arun" },
  {
    $set: {
      "address.city": "Bengaluru",
      "address.country": "India",
      "preferences.theme": "dark"
    }
  }
);

The update modifies the specified nested fields without replacing their parent documents.

Creating a nested path

$set can create missing nested fields when the path can be constructed without conflicting with an incompatible existing value.

If an intermediate field exists as a scalar instead of a document, a nested update may fail. For example, attempting to set address.city when address is a string cannot be treated as an ordinary nested-document update.

Removing nested fields

db.users.updateOne(
  { name: "Arun" },
  { $unset: { "address.postalCode": "" } }
);

This removes only the nested postalCode field.

Data-modeling considerations

If nested structures are frequently updated independently or are very large, consider whether they should remain embedded or be modeled separately. The correct choice depends on consistency requirements, access patterns, and the lifecycle of the related data.

Avoid accidental embedded-document replacement

Using $set: { address: { city: "Bengaluru" } } replaces the entire address value. Use $set: { "address.city": "Bengaluru" } when only the city should change.

Update a nested field without deleting siblings
db.nestedUpdateDemo.insertOne({
  name: "Arun",
  address: {
    city: "Chennai",
    country: "India",
    postalCode: "600001"
  }
});

// Safely update only the city.
db.nestedUpdateDemo.updateOne(
  { name: "Arun" },
  { $set: { "address.city": "Bengaluru" } }
);

// Remove only the postal code.
db.nestedUpdateDemo.updateOne(
  { name: "Arun" },
  { $unset: { "address.postalCode": "" } }
);

db.nestedUpdateDemo.findOne({ name: "Arun" });
💡 Dot notation updates individual nested fields and avoids replacing the entire address document. The unset operation removes only the specified nested field.
Key Takeaways
  • Dot notation targets individual nested fields.
  • Replacing an embedded document removes unspecified sibling fields.
  • $unset can remove a nested field without removing the entire parent document.
  • Nested updates can fail when an intermediate path has an incompatible type.
  • Data modeling should reflect how related information is accessed and updated.
Knowledge Check

A user document contains `address.city`, `address.country`, and `address.postalCode`. What happens when `$set` assigns `{ city: "Bengaluru" }` to the entire `address` field?