Functions
Mongo
Update Many

UpdateMany

Definition

Updates a single document within the collection based on the filter.

Returns: A document containing:

  • matchedCount containing the number of matched documents
  • modifiedCount containing the number of modified documents
  • upsertedId containing the _id for the upserted document.
  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled

Compatibility

You can use UpdateMany() for deployments hosted in the following environments:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud

  • MongoDB Enterprise: The subscription-based, self-managed version of MongoDB

  • MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB

Sintax

The UpdateMany() method has the following form:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "<collection>",
      query = <document>,
      update = <document>,
      options = <document>
   }
)

The UpdateMany() method takes the following parameters:

  • <collection>: The name of the collection to insert the document into.
  • <query>: A document that specifies the query conditions. The query syntax is identical to the read operation query syntax; i.e. UpdateMany() only modifies the matching documents.
  • <update>: A document that specifies the modifications. The update syntax is identical to the update syntax of the UpdateMany() method.
  • <options>: Optional. A document expressing the write concern. Omit to use the default write concern.

Examples

Update using Update Operator Expressions

The restaurant collection contains the following documents:

{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan" },
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : 0 }

The following operation updates a single document where name: "Central Perk Cafe" with the violations field:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "restaurant",
      query = { name = "Central Perk Cafe" },
      update = {
         ["$set"] = { violations = 3 }
      }
   }
)

The operation returns:

{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

If no matches were found, the operation instead returns:

{ "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 }
Update with Aggregation Pipeline

Starting in MongoDB 4.2, the UpdateMany() can use an aggregation pipeline for the update. The pipeline can consist of the following stages:

  • $addFields and its alias $set
  • $project and its alias $unset
  • $replaceRoot and its alias $replaceWith.

Using the aggregation pipeline allows for a more expressive update statement, such as expressing conditional updates based on current field values or updating one field using the value of another field(s).

Example 1

The following examples uses the aggregation pipeline to modify a field using the values of the other fields in the document.

Create a students collection with the following documents:

exports["icmysql"]:MongoInsertMany(
   {
      collection = "students",
      documents = {
         { "_id" = 1, "student" = "Skye", "points" = 75, "commentsSemester1" = "great at math", "commentsSemester2" = "loses temper" },
         { "_id" = 2, "student" = "Matt", "points" = 80, "commentsSemester1" = "great at math", "commentsSemester2" = "loses temper" },
         { "_id" = 3, "student" = "Alicia", "points" = 85, "commentsSemester1" = "great at math", "commentsSemester2" = "loses temper" }
      }
   }
)

Assume that instead of separate commentsSemester1 and commentsSemester2 fields in the first document, you want to gather these into a comments field, like the second document. The following update operation uses an aggregation pipeline to:

  • add the new comments field and set the lastUpdate field.

  • remove the commentsSemester1 and commentsSemester2 fields for all documents in the collection. Make sure that the filter in the update command targets a unique document. The field id in the code below is an example of such a filter:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "students",
      query = { _id = 1 },
      update = {
         ["$set"] = {
            comments = {
               ["$concat"] = {
                  "$commentsSemester1",
                  " ",
                  "$commentsSemester2"
               }
            },
            lastUpdate = { ["$dateToString"] = { format = "%Y-%m-%d", date = { ["$toDate"] = "2020-01-01" } } }
         }
      }
   }
)
Example 2

The aggregation pipeline allows the update to perform conditional updates based on the current field values as well as use current field values to calculate a separate field value.

For example, create a students3 collection with the following documents:

exports["icmysql"]:MongoInsertMany(
   {
      collection = "students3",
      documents = {
         { "_id" = 1, "student" = "Skye", "points" = 75, "commentsSemester1" = "great at math", "commentsSemester2" = "loses temper" },
         { "_id" = 2, "student" = "Matt", "points" = 80, "commentsSemester1" = "great at math", "commentsSemester2" = "loses temper" },
         { "_id" = 3, "student" = "Alicia", "points" = 85, "commentsSemester1" = "great at math", "commentsSemester2" = "loses temper" }
      }
   }
)

The third document _id: 3 is missing the average and grade fields. Using an aggregation pipeline, you can update the document with the calculated grade average and letter grade.

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "students3",
      query = { _id = 3 },
      update = {
         ["$set"] = {
            average = { ["$avg"] = { "$points" } },
            grade = {
               ["$switch"] = {
                  branches = {
                     { case = { ["$gte"] = { "$average", 90 } }, then = "A" },
                     { case = { ["$gte"] = { "$average", 80 } }, then = "B" },
                     { case = { ["$gte"] = { "$average", 70 } }, then = "C" },
                     { case = { ["$gte"] = { "$average", 60 } }, then = "D" }
                  },
                  default = "F"
               }
            }
         }
      }
   }
)
Update with Upsert

The restaurant collection contains the following documents:

{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan", "violations" : 3 },
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : "0" }

The following operation attempts to update the document with name : "Pizza Rat's Pizzaria", while upsert: true :

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "restaurant",
      query = { name = "Pizza Rat's Pizzaria" },
      update = {
         ["$set"] = { violations = 0 }
      },
      options = { upsert = true }
   }
)

Since upsert:true the document is inserted based on the filter and update criteria. The operation returns:

{
   "acknowledged" : true,
   "matchedCount" : 0,
   "modifiedCount" : 0,
   "upsertedId" : 4
}

The collection now contains the following documents:

{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan", "violations" : 3 },
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : "0" },
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 0 }

The name field was filled in using the filter criteria, while the update operators were used to create the rest of the document.

The following operation updates the first document with violations that are greater than 10:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "restaurant",
      query = { violations = { ["$gt"] = 10 } },
      update = {
         ["$set"] = { "Review" = "Review needed." }
      },
      options = { upsert = true }
   }
)

The operation returns:

{
   "acknowledged" : true,
   "matchedCount" : 0,
   "modifiedCount" : 0,
   "upsertedId" : ObjectId("56310c3c0c5cbb6031cafaea")
}

The collection now contains the following documents:

{ "_id" : 1, "name" : "Central Perk Cafe", "Borough" : "Manhattan", "violations" : 3 },
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough" : "Queens", "violations" : 2 },
{ "_id" : 3, "name" : "Empire State Pub", "Borough" : "Brooklyn", "violations" : "0" },
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "violations" : 0 },
{ "_id" : ObjectId("56310c3c0c5cbb6031cafaea"), "violations" : 0, "Review" : "Review needed." }

Since no documents matched the filter, and upsert was true, UpdateMany() inserted the document with a generated _id and the update criteria only.

Update with Write Concern

Given a three member replica set, the following operation specifies a w of majority, wtimeout of 100:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "restaurant",
      query = { name = "Central Perk Cafe" },
      update = {
         ["$set"] = { violations = 3 }
      },
      options = { writeConcern = { w = "majority", wtimeout = 100 } }
   }
)

If the primary and at least one secondary acknowledge each write operation within 100 milliseconds, it returns:

{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

If the acknowledgement takes longer than the wtimeout limit, the following exception is thrown:

WriteConcernError({
   "code" : 64,
   "errmsg" : "waiting for replication timed out",
   "errInfo" : {
     "wtimeout" : true,
     "writeConcern" : {
       "w" : "majority",
       "wtimeout" : 100,
       "provenance" : "getLastErrorDefaults"
     }
   }
})
Specify Collation

Collation allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks.

A collection myColl has the following documents:

{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }

The following operation includes the collation option:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "myColl",
      query = { category = "cafe" },
      update = {
         ["$set"] = { status = "Updated" }
      },
      options = { collation = { locale = "en_US", strength = 1 } }
   }
)
Specify arrayFilters for an Array Update Operations

Starting in MongoDB 3.6, when updating an array field, you can specify arrayFilters that determine which array elements to update.

Update Elements Match arrayFilters Criteria

Create a collection students with the following documents:

exports["icmysql"]:MongoInsertMany(
   {
      collection = "students",
      documents = {
         { _id = 1, grades = [ 95, 92, 90 ] },
         { _id = 2, grades = [ 98, 100, 102 ] },
         { _id = 3, grades = [ 95, 110, 100 ] }
      }
   }
)

To modify all elements that are greater than or equal to 100 in the grades array, use the filtered positional operator $[<identifier>] with the arrayFilters option in the UpdateMany() method:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "students",
      query = { ["$gte"] = 100 }
      update = {
         ["$set"] = { "grades.$[element]" = 100 },
      },
      options = {
         arrayFilters = { [element] = { ["$gte"] = { "$element", 100 } } }
      }
   }
)

The operation updates the grades field of a single document, and after the operation, the collection has the following documents:

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
Update Specific Elements of an Array of Documents

Create a collection students2 with the following documents:

exports["icmysql"]:MongoInsertMany(
   {
      collection = "students2",
      documents = {
         {
            _id = 1,
            grades = {
               { grade = 80, mean = 75, std = 6 },
               { grade = 85, mean = 90, std = 4 },
               { grade = 85, mean = 85, std = 6 }
            }
         },
         {
            _id = 2,
            grades = {
               { grade = 90, mean = 75, std = 6 },
               { grade = 87, mean = 90, std = 3 },
               { grade = 85, mean = 85, std = 4 }
            }
         }
      }
   }
)

To modify the value of the mean field for all elements in the grades array where the grade is greater than or equal to 85, use the filtered positional operator $[<identifier>] with the arrayFilters in the UpdateMany() method:

exports["icmysql"]:MongoUpdateMany(
   {
      collection = "students2",
      query = { },
      update = {
         ["$set"] = { "grades.$[element].mean" = 100 }
      },
      options = {
         arrayFilters = {
            { "elem.grade" = { ["$gte"] = 85 } }
         }
      }
   }
)

The operation updates the array of a single document, and after the operation, the collection has the following documents:

{
   "_id" : 1,
   "grades" : [
      { "grade" : 80, "mean" : 75, "std" : 6 },
      { "grade" : 85, "mean" : 100, "std" : 4 },
      { "grade" : 85, "mean" : 100, "std" : 6 }
    ]
}
{
   "_id" : 2,
   "grades" : [
      { "grade" : 90, "mean" : 75, "std" : 6 },
      { "grade" : 87, "mean" : 90, "std" : 3 },
      { "grade" : 85, "mean" : 85, "std" : 4 }
   ]
}