Update

This lab examines the methods used for updating documents in MongoDB.

db.collection.update()

Modifies an existing document or documents in a collection. The method can modify specific fields of an existing document or documents or replace an existing document entirely, depending on the update parameter. By default, the update() method updates a single document. Set the Multi Parameter to update all documents that match the query criteria.

db.collection.update(query, update, options)

The update() method has the following form:

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

Example: Update one field

This is an example of a document in a books collection:

{
  _id: 1,
  item: "TBD",
  stock: 0,
  info: { publisher: "1111", pages: 430 },
  tags: [ "technology", "computer" ],
  ratings: [ { by: "ijk", rating: 4 }, { by: "lmn", rating: 5 } ],
  reorder: false
}

The following update statement is made up of two parts.

  • The first part is the query, which finds the document with an _id of 1. Queries in update statements can use all of the query operators we examined in the previous section on the find() method.
  • The second part is the update itself. This uses the $set operator, and here we are setting the value of the stock property to 5.
db.books.update(
   { _id: 1 },
   { $set: { stock: 5 } }
)

Example: Update multiple values

See again our example document:

{
  _id: 1,
  item: "TBD",
  stock: 5,
  info: { publisher: "1111", pages: 430 },
  tags: [ "technology", "computer" ],
  ratings: [ { by: "ijk", rating: 4 }, { by: "lmn", rating: 5 } ],
  reorder: false
}

The following update statement sets several properties to new values. Note that to update the publisher property in the info document, info.publisher is used. In updating the ratings array, ratings.1 is used to target the second array element (counting of array elements begins at 0).

db.books.update(
   { _id: 1 },
   {
     $set: {
       item: "ABC123",
       "info.publisher": "2222",
       tags: [ "software" ],
       "ratings.1": { by: "xyz", rating: 3 }
     }
   }
)

Updates with multi and upsert

Update using multi

  • In the example below, the query will find documents where the stock property has a value of less than or equal to 10.
  • The update segment changes the value of the 'reorder' property to 'true'.
  • Here we set one option, the multi option, to true. This means that multiple documents will be changed, if they meet the query criteria. You can specify several options by separating them with commas.
db.books.update(
   { stock: { $lte: 10 } },
   { $set: { reorder: true } },
   { multi: true }
)

Update using upsert

The following update sets the upsert option to true so that update() creates a new document in the books collection if no document matches the parameter:

db.books.update(
   { item: "ZZZ135" },
   {
     item: "ZZZ135",
     stock: 5,
     tags: [ "database" ]
   },
   { upsert: true }
)

If no document matches the parameter, the update operation inserts a document with only the fields and values of the document and a new unique ObjectId for the _id field:

{
  "_id" : ObjectId("542310906694ce357ad2a1a9"),
  "item" : "ZZZ135",
  "stock" : 5,
  "tags" : [ "database" ]
}

Updating arrays and arrays of documents

Updating arrays using arrayFilters

Consider a collection students with the following documents:

db.students.insert([
   { "_id" : 1, "grades" : [ 95, 92, 90 ] },
   { "_id" : 2, "grades" : [ 98, 100, 102 ] },
   { "_id" : 3, "grades" : [ 95, 110, 100 ] }
])

To update all elements that are greater than or equal to 100 in the grades array, use the filtered positional operator $[] with the arrayFilters option:

db.students.update(
   { grades: { $gte: 100 } },
   { $set: { "grades.$[element]" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "element": { $gte: 100 } } ]
   }
)

After the operation, the collection contains the following documents:

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 100, 100 ] }

Updating an array of documents

Consider a collection students2 with the following 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 $[] with the arrayFilters:

db.students2.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
   }
)

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" : 100, "std" : 6 },
      { "grade" : 87, "mean" : 100, "std" : 3 },
      { "grade" : 85, "mean" : 100, "std" : 4 }
   ]
}

Exercises

Carry out the following updates on your grades collection.

  1. Update the document that relates to student 42 and class 18; change the class_id to 19.
  2. Find the document that contains student 38's scores for class 23. Set the third element of the scores array to type "homework" with a score of 60.
  3. Update student 50's scores for class 2. You will need to set the upsert option. Add the following scores:
    • exam: 57.9
    • quiz: 21.2
    • homework: 68.1
  4. Find all scores that are greater than or equal to 99 and set them to 100. (Hint: you should use arrayFilters.)

Further reading

  • Examine the updateOne() and updateMany() methods in the MongoDB reference:

  • Use updateOne() to perform an update on a document (change whatever details you wish).

  • Use updateMany() to update multiple documents (again, make any changes you wish).
  • Use find() before and after your updates to confirm that the changes have been made.

Solutions

Solutions for the exercises in this lab are available here: update_solutions.zip