MongoDB: How to update a field based on another field’s value

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

Overview

Mastering update operations in MongoDB involves understanding how to modify documents based not just on static values but also dynamic data that may depend on other fields within the same document. This practical capability is essential for maintaining data integrity and applying complex data transformations or migrations. This tutorial demonstrates various ways to update a field using values from another field in MongoDB, covering both basic and advanced scenarios.

Understanding the Basics

Before delving into advanced concepts, it’s crucial to cover some groundwork. In MongoDB, updating operations can be performed using methods like updateOne(), updateMany(), and bulkWrite(). When you want to update a field based on the value of another field within the document, you’ll leverage the $set operator in combination with the aggregation pipeline stages introduced in MongoDB version 4.2.

db.collection.updateMany(
  {}, 
  [{ $set: { newField: "$existingField" } }]
);

This command will update all documents in the collection, setting the value of newField to the current value of existingField.

Basic Field Value Copying

Let’s begin with a simple example where we want to duplicate the value of one field to another within each document in a collection:

db.users.updateMany(
  {}, 
  [{ $set: { emailCopy: "$email" } }]
);

All documents in the users collection will now have a new field, emailCopy, which contains a copy of the email field’s value.

Conditional Updates Using Field Values

Sometimes, you may want to perform a conditional update that depends on the value of another field.

db.users.updateMany(
  { subscriptionStatus: "active" },
  [
    { $set: { discountPrice: { $multiply: ["$price", 0.9] } } }
  ]
);

In this case, active subscribers receive a 10% discount, and the discountPrice field is set using the existing price field.

Utilizing Aggregation Framework

The aggregation framework allows even more complex operations. Here’s an example where we calculate a score field based on other numerical fields:

db.students.updateMany(
  {},
  [
    { $set: { score: { $add: ["$homework", "$exam", "$participation"] } } }
  ]
);

This operation creates a score field for each student by summing up the homework, exam, and participation fields.

Incrementing a Field by Another Field’s Value

You may want to increment a field by the value of another field. Here’s how you might apply a bonus to an employee’s salary based on a performance field:

db.employees.updateMany(
  { performance: { $gt: 7 } },
  [{ $set: { salary: { $add: ["$salary", "$bonus"] } } }]
);

The employees who have a performance score above 7 get their salary incremented by the bonus field’s value.

Renaming a Field Based on a Condition

It’s also possible to rename a field conditionally using its own value:

db.products.updateMany(
  { stock: { $lt: 1 } },
  [
    { $rename: { 'stock': 'outOfStock' } },
    { $set: { outOfStock: true } }
  ]
);

Here, products out of stock will have their stock field renamed to outOfStock and set to true.

Advanced Manipulations with Aggregations

More complex transformations can also be achieved using the aggregation pipeline. Imagine an eCommerce scenario where you need to apply discounts to orders depending on the number of items:

db.orders.updateMany(
  {},
  [
    { $set: { discount: { $cond: {
              if: { $gte: [ { $size: "$items" }, 5 ] },
              then: .1,
              else: 0 
          } } } },
    { $set: { total: { $subtract: ["$subtotal", { $multiply: ["$subtotal", "$discount"] }] } } }
  ]
);

Orders containing 5 or more items receive a 10% discount, and the total amount is adjusted accordingly. The $size and $cond operators, alongside the $subtract and $multiply operations, are powerful tools for more sophisticated data transformations within updates.

Using Scripts for Complex Updates

In some scenarios, you may need to write a script to perform updates:

db.collection.find({}).forEach(function(doc) {
  var newValue = calculateNewValue(doc.existingField);
  db.collection.updateOne(
    { _id: doc._id },
    { $set: { newField: newValue } }
  );
});

This script iterates through each document, applies a JavaScript function calculateNewValue, and updates a new field with the returned value.

Conclusion

As these examples illustrate, updating fields based on the value of other fields in MongoDB expands the flexibility of managing your data. MongoDB’s expressive update capabilities and aggregation framework tools offer sophisticated approaches to optimizing your data structure and integrity. Just a few well-crafted queries and operators can significantly streamline complex data operations. Don’t hesitate to consult MongoDB’s extensive documentation and community for even more advanced techniques and best practices.