w3resource

Comprehensive Guide to db.collection.findOneAndUpdate in MongoDB


Understanding db.collection.findOneAndUpdate() in MongoDB

The db.collection.findOneAndUpdate() method in MongoDB performs an update on a single document and returns the original or updated document. This method is particularly useful when you need to update a document and immediately access its content within the same operation.

Syntax:

db.collection.findOneAndUpdate(
   <filter>,
   <update>,
   {
      projection: <document>,
      sort: <document>,
      upsert: <boolean>,
      returnDocument: <string>, // 'before' or 'after'
      maxTimeMS: <number>,
      collation: <document>,
      arrayFilters: [ <filterdocument1>, ... ],
      hint: <document|string>
   }
)

Parameters:

Name Type Description
filter Document Specifies the query criteria to match the document to update. Can include operators like $eq, $gt, or $regex.
update Document Defines the changes to apply to the document. Use operators like $set, $inc, or $unset.
projection Document (Optional) Specifies which fields to include or exclude in the returned document. Example: { name: 1, _id: 0 }.
sort Document (Optional) Determines the order in which documents are processed if multiple documents match the filter. Example: { age: -1 } for descending order.
upsert Boolean (Optional) If true, creates a new document if no documents match the filter. Default is false.
returnDocument String (Optional) Specifies whether to return the document before or after the update. Use 'before' (default) or 'after'.
maxTimeMS Number (Optional) Specifies the maximum time in milliseconds that the operation can run.
collation Document (Optional) Configures how string comparisons are performed, such as locale and case sensitivity. Example: { locale: "en", strength: 2 }.
arrayFilters Array of Documents Specifies conditions for updating elements in an array. Example: [ { "element.qty": { $gte: 10 } } ].
hint Document or String Specifies the index to use for the query. Example: { age: 1 } or "age_1".

Compatibility

You can use db.collection.findOneAndUpdate() 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

Examples

Update a Single Document and Return the Original

Code:

// Update the price of a product and return the original document
db.products.findOneAndUpdate(
  { product: "Laptop" },       // Filter: Match document with product "Laptop"
  { $set: { price: 1200 } },   // Update: Set the price to 1200
  { returnDocument: "before" } // Option: Return the original document
)

Explanation:

  • The filter matches the document where product is "Laptop".
  • The $set operator updates the price field.
  • The returnDocument option specifies that the original document should be returned.

Upsert and Return the Updated Document

Code:

// Insert a new document if no match is found
db.inventory.findOneAndUpdate(
  { item: "Tablet" },          // Filter: Match document with item "Tablet"
  { $set: { qty: 50, price: 300 } }, // Update: Set qty and price
  { upsert: true, returnDocument: "after" } // Options: Upsert and return the new document
)

Explanation:

  • If a document matching the filter doesn’t exist, a new document is created with the specified fields.
  • The returnDocument option ensures the updated (or newly created) document is returned.

Update with Array Filters

Code:

// Update array elements meeting specific conditions
db.orders.findOneAndUpdate(
  { "items.status": "pending" },   // Filter: Match documents with pending items
  { $set: { "items.$[item].status": "processed" } }, // Update: Set status to "processed"
  {
    arrayFilters: [ { "item.status": "pending" } ], // Array filter: Only pending items
    returnDocument: "after" // Return updated document
  }
)

Explanation:

  • $[item] refers to elements in the items array that match the condition specified in arrayFilters.
  • The status field of all pending items is updated to "processed".

Returned Acknowledgment

The findOneAndUpdate method returns a single document that matches the query and update conditions. Example return:

Code:

{
  "product": "Laptop",
  "price": 1000,
  "category": "Electronics"
}

Explanation:

  • If the returnDocument option is set to "before", the original document is returned.
  • If set to "after", the updated document is returned.

Error Scenarios

Missing Update Operators

Code:

db.products.findOneAndUpdate(
  { product: "Phone" },
  { price: 800 } // Error: Missing update operator
)

Error:

Code:

Update document requires update operators like $set

Solution:

Always include operators like $set, $inc, etc., unless replacing the entire document.

Invalid Array Filters

Code:

db.orders.findOneAndUpdate(
  { "items.status": "pending" },
  { $set: { "items.$[item].status": "processed" } },
  { arrayFilters: [ { "item.invalidField": true } ] }
)

Error:

Cannot apply array updates with invalid filter criteria.

Solution:

Ensure that the arrayFilters condition targets valid fields within the array.

Best Practices

1. Use Return Options Wisely

  • Set returnDocument to "after" if the updated data is immediately required.

2. Validate Filters

  • Test filters with find() queries before applying updates to avoid unintended changes.

3. Avoid Empty Filters

  • Prevent accidental updates to all documents by specifying precise filter criteria.

4. Use Indexes

  • Apply indexes to fields used in the filter to optimize performance.

5. Array Updates

  • Leverage arrayFilters for targeted updates within arrays to maintain precision.


Become a Patron!

Follow us on Facebook and Twitter for latest update.

It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.

https://www.w3resource.com/mongodb/mongodb-db-collection-findoneandupdate.php