MongoDB - Find and Modify Query

db.collection.findAndModify()

Finds a document in the collection that matches the query parameters, modifies only one document and returns either the original document, or by using the new option, will return the document with the modifications made during the update operation.

The findAndModify() method has the following embedded document structure:

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

In MongoDB, the db.collection.findAndModify() method accepts the following document parameters within the embedded document fields.

query
The condition for the modification. The query field uses the same query selectors as the db.collection.find() method. The query may match multiple documents, however, findAndModify() will only select one document to modify.

sort
Determines which document the operation modifies if the query matches more than one document. findAndModify() will only modify the first document in the indicated sort order of this argument.|

remove
You must select whether to remove or the update the field. This condition removes the document specified in the query field. Set this to true to remove the selected document . False by default.|

update
Specify either the remove or the update on the data field. This will perform an update of the document returned by the query. The update field employs the same update operators or field: values required to modify the selected document.|

new
When this option is true, it will return the modified document rather than the original document. The findAndModify() method ignores the new option for remove operations. The default is false.|

fields
A set of fields to return in the response. The fields document specifies an inclusion of a field with 1 or 0.|

upsert
Used in conjunction with the update field. When true, findAndModify() will create a new document if no documents match the query, or if documents match the query, findAndModify() will performs the update as expected. In order to avoid multiple upserts, you must ensure that the query fields are uniquely indexed. This is set to false by default.|

Our Return Data

Returns null if findAndModify does not match a document in the collection. If the query matches a document, findAndModify() returns the removed document.

For update operations, findAndModify() returns one of the following:

If the new parameter is not set or is false:

  • the pre-modified document if the query matches a document in the collection;
  • otherwise, it returns null.

If new is set to true:

  • returns the modified document if the query matches a document in the collection;
  • the inserted document if upsert is set to true and no documents match the query;
  • otherwise, it returns null.
findAndModify() Examples

Update and Return
In the below example, the query returns an existing document in the people collection matching the selected query document parameters.

connecting to: test  
> db.people.findAndModify({
      query: { 'name' : "Michael Jones",
               'status' : "active",
               'role' : 'moderator',
               'rating' : { $gt: 50 },

             },
      sort: { rating: 1 },
      update: { $inc: { rating: 98 } }
  });

This method will perform the following actions:

  • The query finds a document in the people collection where the name field has the value Michael Jones, the status field has the value active and the moderator rating field has a value greater than 10.

  • The sort document in the query orders the results of the query to lookup the documents in ascending order. If more than one document matches the query condition, the findAndModify() method will select the first document as indicated by this sort order.

  • The update sets the value of the moderator rating field to 98.

For the above query method; MongoDB returns the following document as a response:

{
    "_id" : ObjectId("564e2..."),
    "name" : "Michael Jones",
    "status" : "active",
    "role" " : "moderator",
    "rating" : 95
}

Note that this is the pre-modified document returned by MongoDB. If you look closely, it still shows this moderators's rating of 95, which we just increased to 98.

Update & Upsert

The update method includes an upsert option so that either an update operation is executed when a document matches the query document or, if no matching document can be located, upsert set to true will create a new document:

connecting to: test  
> db.people.findAndModify({
    query: { 'name' : 'Gabriela Jones',
             'role' : 'moderator',
             'status' : 'active',
             'rating' : 100 },
    sort: { rating: 1 },
    update: { $inc: { rating: 85 } },
    upsert: true
});

If the findAndModify() method locates a document matching the query document, the method executes an update.

If the findAndModify() method can not find a documents matching the query, the method creates a new document. And because this query document included the sort option, it returns an empty document { } instead of null.

Return New Document

To return the new document modified by the findAndModify() method, you must include both the upsert equals true option and the new equals true option.

The findAndModify() method will either update a matching document and returns the updated document; or, if no matching document can be found, inserts a new document and returns the newly inserted document.

In the below example, no document in the people collection matches the query condition:

connecting to: test  
> db.people.findAndModify({
    query: {
              'name ' : 'Robert Jones',
              'status' : 'active',
              'role' : 'moderator',
           },
    sort: { 'status': 'active' },
    update: { $inc: { 'rating': 95 } },
    upsert: true,
    new: true
});

The findAndModify() method returns our newly inserted document:

{
   "_id" : ObjectId("563e1..."),
   "name" : "Robert Jones",
   "role" : 'moderator',
   "rating" : 95,
   "status" : "active"
}
Sort and Remove

To sort and remove a document from the people collection, you must include a sort specification on the moderator rating field, the following example removes from the people collection a single document with the status value of active and the lowest rating among the matching documents:

connecting to: test  
> db.people.findAndModify(
   {
     query: { 'status' : 'active' },
     sort: { rating: 1 },
     remove: true
   }
);

The findAndModify() method returns the document that was removed from the collection during the operation:

{
   "_id" : ObjectId("5641e..."),
   "name" : "Trent Jones",
   "role" : "admin",
   "status" : "active",
   "rating" : 35
}

Craig Derington

Veteran full stack web dev focused on deploying high-performance, responsive, modern web applications using Python, NodeJS, Django, Flask, MongoDB and MySQL.

comments powered by Disqus