w3resource

MongoDB: db.collection.findAndModify() method

db.collection.findAndModify

The db.collection.findAndModify() method is used to modify and returns a single document. By default, the returned document does not include the modifications made on the update. To return the document with the modifications made on the update, use the new option.

The findAndModify() method has the following form:


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

Syntax:

db.collection.findAndModify(document)

Parameters:

Name Description Required /
Optional
Type
query The selection criteria for the modification. The query field employs the same query selectors as used in the db.collection.find() method. Although the query may match multiple documents, findAndModify() will only select one document to modify. Optional document
sort Determines which document the operation modifies if the query selects multiple documents. findAndModify() modifies the first document in the sort order specified by this argument. Optional document
remove Must specify either the remove or the update field. Removes the document specified in the query field. Set this to true to remove the selected document . The default is false. Required boolean
update Must specify either the remove or the update field. Performs an update of the selected document. The update field employs the same update operators or field: value specifications to modify the selected document. Required document
new When true, returns the modified document rather than the original. The findAndModify() method ignores the new option for remove operations. The default is false. Optional boolean
fields A subset of fields to return. The fields document specifies an inclusion of a field with 1, as in: fields: { <field1>: 1, <field2>: 1, ... }. Optional document
upsert Used in conjunction with the update field.
When true, findAndModify() creates a new document if no document matches the query, or if documents match the query, findAndModify() performs an update. To avoid multiple upserts, ensure that the query fields are uniquely indexed.
The default is false.
Optional boolean

Return Data

For remove operations, if the query matches a document, findAndModify() returns the removed document. If the query does not match a document to remove, findAndModify() returns null.

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

  • If the new parameter is not set or is false:
    • the pre-modification document if the query matches a document;
    • otherwise, null.
  • If new is true:
    • the modified document if the query returns a match;
    • the inserted document if upsert: true and no document matches the query;
    • otherwise, null.

Sample document in the restaurants collection:

{
  "address": {
     "building": "1007",
     "coord": [ -73.856077, 40.848447 ],
     "street": "Morris Park Ave",
     "zipcode": "10462"
  },
  "borough": "Bronx",
  "cuisine": "Bakery",
  "grades": [
     { "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 },
     { "date": { "$date": 1378857600000 }, "grade": "A", "score": 6 },
     { "date": { "$date": 1358985600000 }, "grade": "A", "score": 10 },
     { "date": { "$date": 1322006400000 }, "grade": "A", "score": 9 },
     { "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 }
  ],
  "name": "Morris Park Bake Shop",
  "restaurant_id": "30075445"
}
.....

Example: MongoDB: db.collection.findAndModify() method

Here we have created a duplicate copy to restaurants collection as restaurants1. Now we will work with this collection.

The following method updates and returns an existing document in the restaurants1 collection where the document matches the query criteria:


db.restaurants1.findAndModify({
    query: { "name" : "Douglaston Club" },
    sort: { cuisine: 1 },
    update: { $inc: { "age": 1 } },
});

This method performs the following actions:

  1. The query finds a document in the restaurants1 collection where the name field has the value Douglaston Club.

  2. The sort orders the results of the query in ascending order. If multiple documents meet the query condition, the method will select for modification the first document as ordered by this sort.

  3. The update increments the value of the age  field by 1.

  4. The method returns the original (i.e. pre-modification) document selected for this update:


{
        "_id" : ObjectId("55c3043ab165fa6355ec5cda"),
        "address" : {
                "building" : "600",
                "coord" : [
                        -73.7522366,
                        40.7766941
                ],
                "street" : "West Drive",
                "zipcode" : "11363"
        },
        "borough" : "Queens",
        "cuisine" : "American ",
        "grades" : [
                {
                        "date" : ISODate("2013-12-04T00:00:00Z"),
                        "grade" : "A",
                        "score" : 13
                },
                {
                        "date" : ISODate("2013-06-13T00:00:00Z"),
                        "grade" : "A",
                        "score" : 13
                },
                {
                        "date" : ISODate("2012-12-06T00:00:00Z"),
                        "grade" : "A",
                        "score" : 9
                },
                {
                        "date" : ISODate("2012-04-12T00:00:00Z"),
                        "grade" : "A",
                        "score" : 2
                },
                {
                        "date" : ISODate("2011-07-30T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                }
        ],
        "name" : "Douglaston Club",
        "restaurant_id" : "40364858"
}

Now execute the following statement and see the result.

db.restaurants1.find({"name" : "Douglaston Club"}).pretty();

Here we see that as there was no age field in the documents, so it did not update rather a new field age have been created.


{
        "_id" : ObjectId("55c3043ab165fa6355ec5cda"),
        "address" : {
                "building" : "600",
                "coord" : [
                        -73.7522366,
                        40.7766941
                ],
                "street" : "West Drive",
                "zipcode" : "11363"
        },
        "borough" : "Queens",
        "cuisine" : "American ",
        "grades" : [
                {
                        "date" : ISODate("2013-12-04T00:00:00Z"),
                        "grade" : "A",
                        "score" : 13
                },
                {
                        "date" : ISODate("2013-06-13T00:00:00Z"),
                        "grade" : "A",
                        "score" : 13
                },
                {
                        "date" : ISODate("2012-12-06T00:00:00Z"),
                        "grade" : "A",
                        "score" : 9
                },
                {
                        "date" : ISODate("2012-04-12T00:00:00Z"),
                        "grade" : "A",
                        "score" : 2
                },
                {
                        "date" : ISODate("2011-07-30T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                }
        ],
        "name" : "Douglaston Club",
        "restaurant_id" : "40364858",
        "age" : 1
}

Now to return the modified document, add the new:true option to the method.


db.restaurants1.findAndModify({
    query: { "name" : "Douglaston Club" },
    sort: { cuisine: 1 },
    update: { $inc: { "age": 1 } },
    new : true
});

Output


{
        "_id" : ObjectId("55c3043ab165fa6355ec5cda"),
        "address" : {
                "building" : "600",
                "coord" : [
                        -73.7522366,
                        40.7766941
                ],
                "street" : "West Drive",
                "zipcode" : "11363"
        },
        "borough" : "Queens",
        "cuisine" : "American ",
        "grades" : [
                {
                        "date" : ISODate("2013-12-04T00:00:00Z"),
                        "grade" : "A",
                        "score" : 13
                },
                {
                        "date" : ISODate("2013-06-13T00:00:00Z"),
                        "grade" : "A",
                        "score" : 13
                },
                {
                        "date" : ISODate("2012-12-06T00:00:00Z"),
                        "grade" : "A",
                        "score" : 9
                },
                {
                        "date" : ISODate("2012-04-12T00:00:00Z"),
                        "grade" : "A",
                        "score" : 2
                },
                {
                        "date" : ISODate("2011-07-30T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                }
        ],
        "name" : "Douglaston Club",
        "restaurant_id" : "40364858",
        "age" : 2
}

Retrieve the restaurants data from here

Behavior

Upsert and Unique Index

When findAndModify() includes the upsert: true option and the query field(s) is not uniquely indexed, the method could insert a document multiple times in certain circumstances.

Previous: db.collection.find() method
Next: db.collection.findOne() method



Follow us on Facebook and Twitter for latest update.