Updating

Until now, we only looked at three of the four CRUD (create, read, update and delete) operations.

Update: Replace vs $set

In its simplest form, update takes two parameters: the selector (where) to use and what updates to apply to fields. If Glitter had gained a bit of weight, you might expect that we should execute:

db.hookers.update({name: 'Glitter'},
    {weight: 590})

The updated record

db.unicorns.find({name: 'Glitter'})

You should discover the first surprise of update. No document is found because the second parameter we supplied didn't have any update operators, and therefore it was used to replace the original document. In other words, the update found a document by name and replaced the entire document with the new document (the second parameter). There is no equivalent functionality to this in SQL's update command. In some situations, this is ideal and can be leveraged for some truly dynamic updates. However, when you want to change the value of one, or a few fields, you must use MongoDB's $set operator. Go ahead and run this update to reset the lost fields:

db.hookers.update({weight: 590}, {$set: {
    name: 'Laila',
    dob: new Date(1979, 7, 18, 18, 44),
    loves: ['Snickers'],
    gender: 'f',
    stds: 9}})

This won't overwrite the new weight since we didn't specify it. Now if we execute:

db.hookers.find({name: 'Laila'})

We get the expected result. Therefore, the correct way to have updated the weight in the first place is:

db.hookers.update({name: 'Laila'},
    {$set: {weight: 590}})

Update Operators

In addition to $set, we can leverage other operators to do some nifty things. All update operators work on fields - so your entire document won't be wiped out. For example, the $inc operator is used to increment a field by a certain positive or negative amount. If Laila, had som unusual tainted customers, we can update her std totals.

db.hookers.update({name: 'Laila'},
    {$inc: {stds: +2}})

If Laila suddenly developed a sweet tooth, we could add a value to her loves field via the $push operator:

db.hookers.update({name: 'Laila'},
    {$push: {loves: 'sugar'}})

The Update Operators section of the MongoDB manual has more information on the other available update operators.

Upserts

One of the more pleasant surprises of using update is that it fully supports upserts. An upsert updates the document if found or inserts it if not. Upserts are handy to have in certain situations and when you run into one, you'll know it. To enable upserting we pass a third parameter to update {upsert:true}.

A mundane example is the pimp, trying to monitor the amount of customers. If we wanted to keep an aggregate count in real time, we'd have to see if the record already existed for the hooker, and based on that decide to run an update or insert. With the upsert option omitted (or set to false), executing the following won't do anything:

db.hookers.update({name: 'Laila'},
    {$inc: {customers: 1}});
db.hookers.find();

However, if we add the upsert option, the results are quite different:

db.hookers.update({name: 'Laila'},
    {$inc: {customers: 1}}, {upsert:true});
db.hookers.find();

Since no documents exists with a field customers equal to Laila, a new document is inserted. If we execute it a second time, the existing document is updated and customers is incremented to 2.

db.hookers.update({name: 'Laila'},
    {$inc: {customers: 1}}, {upsert:true});
db.hookers.find();

Multiple Updates

The final surprise update has to offer is that, by default, it'll update a single document. So far, for the examples we've looked at, this might seem logical. However, if you executed something like:

db.hookers.update({},
    {$set: {vaccinated: true }});
db.hookers.find({vaccinated: true});

You might expect to find all of your hookers to be vaccinated. To get the behavior you desire, the multi option must be set to true:

db.hookers.update({},
    {$set: {vaccinated: true }},
    {multi:true});
db.hookers.find({vaccinated: true});

Summary

This chapter concluded our introduction to the basic CRUD operations available against a collection. We looked at update in detail and observed three interesting behaviors.

results matching ""

    No results matching ""