findOneAndUpdate() and findAndModify() in MongoDB

FindOneAndUpdate And FindAndModify Featured Image

in this tutorial, I will explain using the findOneAndUpdate() and findAndModify() functions in MongoDB.

Both findOneAndUpdate() and findAndModify() functions perform a find and an update operation inside the mongo shell.

This guide aims to provide readers with examples to illustrate the usage of the two.

Syntaxes for findOneAndUpdate() and findAndModify() Functions

Let us take a quick look at the syntaxes for both the functions below:

1. findOneAndUpdate()

db.collection.findOneAndUpdate( filter, update, options )

2. findAndModify()

db.collection.findAndModify(document)

Using the findOneAndUpdate() and findAndModify() Functions

Let us now get started by looking at some examples for both the functions in MongoDB inside the mongo shell. Below is the collection that I will be using for today’s tutorial.

{
        "_id" : ObjectId("602eb6c728ff814b64eb3411"),
        "name" : "Stephanie",
        "age" : 22,
        "breed" : "Persian Cat",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : true
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "30th May, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}
{
        "_id" : ObjectId("602eb73728ff814b64eb3412"),
        "name" : "Whiskers",
        "age" : 4,
        "breed" : "Scottish Fold",
        "personality" : {
                "dogFriendly" : false,
                "childFriendly" : true
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "5th Mar, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}
{
        "_id" : ObjectId("602eb84628ff814b64eb3413"),
        "name" : "Krissy",
        "age" : 6,
        "breed" : "Turkish Angora",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "12th Dec, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}
{
        "_id" : ObjectId("602ebc5ea78db75e09057cd0"),
        "name" : "Cassy",
        "age" : 16,
        "breed" : "Japanese Angora",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "26th Jul, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}
{
        "_id" : ObjectId("602ebc9da78db75e09057cd1"),
        "name" : "Shane",
        "age" : 11,
        "breed" : "Bobtail",
        "personality" : {
                "dogFriendly" : false,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "16th Sep, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}
{
        "_id" : ObjectId("602ebed7a78db75e09057cd2"),
        "name" : "Phoebe",
        "age" : 21,
        "breed" : "Bobtail",
        "personality" : {
                "dogFriendly" : false,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "20th Jan, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

Operating on String Value Fields Using the findOneAndUpdate() and findAndModify() Functions

In this example, I will use both the functions on string fields and demonstrate them as different examples – of course!

Using findOneAndUpdate()

Let’s say Stephanie got adopted and her owner has changed her name to Renee.

> db.cats.findOneAndUpdate({"name": "Stephanie"}, { $set: {"name": "Renee" }})
{
        "_id" : ObjectId("602eb6c728ff814b64eb3411"),
        "name" : "Stephanie",
        "age" : 22,
        "breed" : "Persian Cat",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : true
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "30th May, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

You must have noticed that the findOneAndUpdate() function immediately returns the selected documents in their unchanged form. Let us see if a cat named Renee exists:

> db.cats.findOne({"name": "Renee"})
{
        "_id" : ObjectId("602eb6c728ff814b64eb3411"),
        "name" : "Renee",
        "age" : 22,
        "breed" : "Persian Cat",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : true
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "30th May, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

And it does!

Using findAndModify()

Let’s say we mistakenly set the breed of some cats Bobtail instead of Exotic Shorthair. Remember, the findAndModify() function only updates the first document that matches the query.

> db.cats.findAndModify(
...    {
...      query: { breed: "Bobtail" },
...      update: { $set: { breed: "Exotic Shorthair" } }
...    }
... )
{
        "_id" : ObjectId("602ebc9da78db75e09057cd1"),
        "name" : "Shane",
        "age" : 11,
        "breed" : "Bobtail",
        "personality" : {
                "dogFriendly" : false,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "16th Sep, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

We have again received the unmodified version of the document. To return with updated values, pass the new option as true. Let us try out and simultaneously check if the document is updated or not. We will do this for the other Bobtail we have – Phoebe.

> db.cats.findAndModify(
...    {
...      query: { breed: "Bobtail" },
...      update: { $set: { breed: "American Shorthair" } },
...      new: true
...    }
... )
{
        "_id" : ObjectId("602ebed7a78db75e09057cd2"),
        "name" : "Phoebe",
        "age" : 21,
        "breed" : "American Shorthair",
        "personality" : {
                "dogFriendly" : false,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "20th Jan, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

Great! We have been returned the updated value by the function.

Operating on Embedded Documents Using the findOneAndUpdate() and findAndModify() Functions

In this example, I will use both the functions and operate on an embedded document.

Using findOneAndUpdate()

Let’s say Whiskers has got along well with dogs now and we no more want to denounce him for not being a dog-friendly kitty. We will dot notation to access these embedded document fields.

> db.cats.findOneAndUpdate({name: "Whiskers"}, { $set: {"personality.dogFriendly": true }})
{
        "_id" : ObjectId("602eb73728ff814b64eb3412"),
        "name" : "Whiskers",
        "age" : 4,
        "breed" : "Scottish Fold",
        "personality" : {
                "dogFriendly" : false,
                "childFriendly" : true
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "5th Mar, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

Looks like the function was successful. Let us take a look:

> db.cats.findOne({"name": "Whiskers"})
{
        "_id" : ObjectId("602eb73728ff814b64eb3412"),
        "name" : "Whiskers",
        "age" : 4,
        "breed" : "Scottish Fold",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : true
        },
        "moreDetails" : {
                "cost" : 30000,
                "adoptionDate" : "5th Mar, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

Perfect! We now have the dogFriendly field as true 😊.

Using findAndModify()

Let us change the cost of Krissy to 23000.

> db.cats.findAndModify(
...    {
...      query: { name: "Krissy" },
...      update: { $set: { "moreDetails.cost": 23000} },
...      new: true
...    }
... )
{
        "_id" : ObjectId("602eb84628ff814b64eb3413"),
        "name" : "Krissy",
        "age" : 6,
        "breed" : "Turkish Angora",
        "personality" : {
                "dogFriendly" : true,
                "childFriendly" : false
        },
        "moreDetails" : {
                "cost" : 23000,
                "adoptionDate" : "12th Dec, 2021"
        },
        "likes" : [
                "fish",
                "milk",
                "chicken",
                "blankets"
        ]
}

Awesome! We now have the updated value returned with the cost set to 23000.

Conclusion

Learn to use the findOneAndUpdate() and findAndModify() functions in MongoDB.

References

https://docs.mongodb.com/v4.4/reference/method/db.collection.findAndModify/

https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/