MongoDB db.collection.findAndModify() method (with examples)

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

Overview

The findAndModify() method in MongoDB plays a crucial role in situations where an operation requires searching for a document and, possibly, updating it atomically. This ensures that the operation is completed without interruption by other database operations, crucial in high-concurrency environments. This tutorial will dive deep into the findAndModify() method, illustrating its use with various examples, from basic to more advanced scenarios.

The findAndModify() Method

The findAndModify() method searches for a single document based on the search query and can either update it, remove it, or replace it with a new document. It atomically modifies the found document and returns the original document by default. Optionally, it can return the updated or new document if specified. The operation is pivotal for tasks that require immediate reflection of the modification like counters, status updates, or document replacements that need atomicity to ensure data integrity.

To begin exploring this method, let’s set up our environment and pre-requisites:

  1. Make sure MongoDB server is running.
  2. Connect to the MongoDB shell or use a MongoDB client that allows running commands.

Basic Usage

At its core, findAndModify() requires specifying a query to find a document, along with actions such as update, remove, or replace. Here’s the basic syntax:

db.collection.findAndModify({
  query: { <query> },
  update: { <update> },
  remove: <boolean>,
  new: <boolean>,
  upsert: <boolean>,
  sort: { <fields> },
  fields: { <fields> }
})

Let’s start with a simple example where we’ll update a document’s status:

db.userCollection.findAndModify({
  query: { username: 'jdoe' },
  update: { $set: { status: 'active' } },
  new: true
});

This operation searches for a user with username ‘jdoe’ and updates the status to ‘active’. The new option set to true means the method returns the updated document.

Incrementing a Counter

Use cases such as keeping a counter often benefit from findAndModify(). Here’s how to atomically increment a counter:

db.counterCollection.findAndModify({
  query: { counterId: 1 },
  update: { $inc: { sequence_value: 1 } },
  new: true
});

In this example, we atomically increment the sequence_value of the document with counterId 1 and return the updated document.

Advanced Scenarios

Now that we’ve covered some basic operations, let’s dive into more complex uses of findAndModify().

Conditional Updates and Upserts

In certain cases, you might want to perform an update only if specific conditions are met or insert a new document if no matching document is found. Here’s an example:

db.sales.findAndModify({
  query: { item: 'apple', day: { $gt: '2023-01-01' } },
  update: { $set: { status: 'sold' }, $inc: { quantity: -1 } },
  upsert: true
});

This performs a conditional update or inserts a new document (upsert) depending on the availability of the matching document.

Sorting and Selecting Specific Fields

When multiple documents match the query criteria, findAndModify() allows sorting and limiting the fields of the returned document. Consider a scenario where you want the method to affect the oldest document:

db.logCollection.findAndModify({
  query: { status: 'open' },
  sort: { created_at: -1 },
  update: { $set: { status: 'closed' } },
  fields: { _id: 0, status: 1, message: 1 },
  new: true
});

In this example, documents are sorted by created_at in descending order, and only specific fields are returned in the final document.

Conclusion

The findAndModify() method is a powerful tool for MongoDB users, offering a way to atomically find, modify, and return documents within a single operation. Throughout this guide, we explored its syntax and usage through various examples, laying a foundation for implementing complex data manipulations with precision and efficiency.