Lecture
In the first chapter, we covered three of the four CRUD operations (create, read, update and delete). This chapter is devoted to the fourth: update. update has some quirks of its own, which is why we're dedicating a whole chapter to it.
In its simplest form, update takes 2 arguments: a selector (where) to find the document, and what to update the matching field with. To make Moons gain some weight, we use the following query:
db.unicorns.update({name: 'Moons'}, {weight: 890})
(If, during your experiments, you deleted the data from the previously created unicorns collection, run remove on all the documents and re-insert them using the code from chapter 1)
In real life, of course, you should update documents by selecting them via _id, but since I don't know what _id MongoDB generated for you, we'll select by name instead - name. Now, let's take a look at the updated record:
db.unicorns.find({name: 'Moons'})
Here's the first surprise that update has in store for us. The document isn't found, because the second parameter is used to completely replace the original. In other words, update found the document by name and replaced it entirely with the new document (its second parameter). This is where it differs from the SQL UPDATE command. Sometimes this is exactly what you want, and it can be used for some genuinely dynamic updates. However, if you only need to change a couple of fields, it's best to use the $set modifier:
db.unicorns.update({weight: 590}, {$set: {name: 'Moons', dob: new Date(1999, 7, 18, 18, 44), loves: ['apple'], gender: 'm', vampires: 99}})
db.unicorns.find({name: 'Moons'})
we'll get the expected result. So, in the first example, the correct way to update weight would have been:
db.unicorns.update({name: 'Moons'}, {$set: {weight: 590}})
Besides $set, there are other modifiers you can use for various neat tricks. All of these update modifiers operate on fields - so your document never ends up being overwritten entirely. For example, the $inc modifier is used to change a field by a positive (increase) or negative (decrease) amount. For instance, if the unicorn Pilot was mistakenly credited with killing a couple of extra vampires, we can fix that mistake as follows:
db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}})
db.unicorns.update({name: 'Aurora'}, {$push: {loves: 'sugar'}})
One of the pleasant surprises of the update operation is the ability to do an update/insert (upsert, from update - to update, and insert - to insert). An upsert updates the document if it's found, or creates a new one if it isn't. Upserts are a useful thing in some situations; you'll know it when you hit one. To allow insertion on update, set the third parameter to true.
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}});
db.hits.find();
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);
db.hits.find();
db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);
db.hits.find();
The last surprise of the update method is that, by default, it only updates a single document. So far this has made sense given the examples we've looked at. However, if you run something like:
db.unicorns.update({}, {$set: {vaccinated: true }});
db.unicorns.find({vaccinated: true});
then you would naturally expect all the unicorns to become (vaccinated). For this to work, you need to set the fourth parameter to true:
db.unicorns.update({}, {$set: {vaccinated: true }}, false, true);
db.unicorns.find({vaccinated: true});
This chapter has wrapped up our introduction to the basic CRUD operations on collections. We took a close look at update and saw three of its interesting modes of operation. First, unlike the SQL UPDATE command, MongoDB's update replaces the entire document. That's why the $set modifier is so useful. Second, update supports an intuitively simple update/insert (upsert), which is especially useful with the $inc modifier. And finally, third, by default, update only updates the first document it finds.
Comments