Click here to Skip to main content
Click here to Skip to main content

MongoDB - Updating Records

, 6 May 2013
Rate this:
Please Sign up or sign in to vote.
Queries to explain update items in MongoDB

Introduction

I have covered the basic queries (select, insert and delete) of MongoDB in my last post, now I will describe here how to update records in MongoDB. Update records is one the four basic operations CRUD (create, read, update and delete) for any database we required. MondoDB also provided its update queries, with more sophisticated tasks.

Update queries function in Mongo are not straight forward like SQL databases. It is a little more enhanced functional component than simple update. You will find that it facilitates the general operations of routine development tasks, and we could have made our database operations with less complications in the data layer.

Background

Update queries are capable of doing the following jobs:

  • It could replace the entire document (recall, you could think of it as DataRow in .NET environment)
  • Simply update the records like in simple SQL databases, the number of fields you specify will be updated with the provided condition.
  • Provide special $inc modifier, if you need to increment or decrement a field's value.
  • $push modifier adds a value to the array (recall, you could place entire arrays in your document's fields)
  • An upsert updates the document if found or inserts it if not.

Description

In its simplest form, update takes 2 arguments: the selector (where) to use and what field to update with. If Imran has to change the category he played, we could execute:

db.KarachiTigers.update({name: 'Imran'}, {category: 'Bowler'})

If this was real code, you'd probably update your records by _id, but since I don't know what _id MongoDB generated for you, we'll stick to names. Now, if we look at the updated record:

db.KarachiTigers.find({name: 'Imran'})

You should discover updates first surprise. No document is found because the second parameter we supply is used to replace the original. In other words, the update found a document by name and replaced the entire document with the new document (the 2nd parameter). This is different than how SQL's update command works. In some situations, this is ideal and can be leveraged for some truly dynamic updates. However, when all you want to do is change the value of one, or a few fields, you are best to use MongoDB's $set modifier:

db.KarachiTigers.update({name: 'Imran'}, {$set: {category: 'Bowler', dob: new Date
(1979, 7, 18, 18, 44), hobbies: ['cricket'], gender: 'm'}})

This will reset the lost fields. It won't overwrite the new category since we didn't specify it. Now if we execute:

db.KarachiTigers.find({name: 'Imran'})

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

db.KarachiTigers.update({name: 'Imran'}, {$set: {category: 'Bowler'}})

In addition to $set, we can leverage other modifiers to do some interesting things. All of these update modifiers work on fields - so your entire document won't be wiped out. For example, the $inc modifier is used to increment a field by a certain positive or negative amount. For example, if Amir was incorrectly awarded a wicket, we could correct the mistake by executing:

db.KarachiTigers.update({name: 'Amir'}, {$inc: {wickets: -1}})

If Saeed Ajmal has to update his bowling actions, e.g., he could bowl off-spin and doosra, we could set the array items defined in actions field of the document:

db.KarachiTigers.update({name: 'Saeed Ajmal'}, {$set: {actions: ['off-spin', 'doosra']}})

Let's say, if Saeed Ajmal suddenly developed a teesra bowling action, we could add a value to his actions field via the $push modifier:

db.KarachiTigers.update({name: 'Saeed Ajmal'}, {$push: {actions: 'teesra'}})

The Updating section of the MongoDB website has more information on the other available update modifiers.

One of updates more pleasant surprises 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 set a third parameter to true. An everyday example is a hit counter for a website. If we wanted to keep an aggregate count in real time, we'd have to see if the record already existed for the page, and based on that decide to run an update or insert. With the third parameter omitted (or set to false), executing the following won't do anything:

db.hits.update({page: 'cricket updates'}, {$inc: {hits: 1}});
db.hits.find();

However, if we enable upserts, the results are quite different:

db.hits.update({page: 'cricket updates'}, {$inc: {hits: 1}}, true);
db.hits.find();

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

db.hits.update({page: 'cricket updates'}, {$inc: {hits: 1}}, true);
db.hits.find();

A non-upsert update may or may not modify an existing object. An upsert will either modify an existing object or insert a new object. The client may determine if it's most recent message on a connection updated an existing object by subsequently issuing a getlasterror command (db.runCommand( "getlasterror" )).

  • If the result of the getlasterror command contains an updatedExisting field, the last message on the connection was an update request.
  • If the updatedExisting field's value is true, that update request caused an existing object to be updated
  • If updatedExisting is false, no existing object was updated.
  • An "upserted" field will contain the new _id value if an insert is performed.

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.KarachiTigers.update({}, {$set: {qualified: true }});
db.KarachiTigers.find({qualified: true});

You'd likely expect to find all of your team members to be qualified. To get the behavior you desire, a fourth parameter must be set to true:

db.KarachiTigers.update({}, {$set: {qualified: true }}, false, true);
db.KarachiTigers.find({qualified: true});

Points of Interest

We concluded our introduction to the basic CRUD operations available against a collection. We looked at update in detail and observed three interesting behaviors. First, unlike an SQL update, MongoDB's update replaces the actual document. Because of this, the $set modifier is quite useful. Secondly, update supports an intuitive upsert which is particularly useful when paired with the $inc modifier. Finally, by default, update only updates the first found document. Do remember that we are looking at MongoDB from the point of view of its shell. The driver and library you use could alter these default behaviors or expose a different API.

History

  • 27th February, 2012: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

m-idrees
Team Leader Innovative Solutions
Pakistan Pakistan
Software Engineer,
Karachi - Pakistan.
http://idreesdotnet.blogspot.com/
Follow on   Twitter

Comments and Discussions

 
QuestionIDE PinmemberAntonio Barros2-Jun-14 6:16 
GeneralMy vote of 5 PinmemberVitorHugoGarcia7-May-13 6:16 
GeneralRe: My vote of 5 PinmemberM-Idrees-pk7-May-13 18:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 7 May 2013
Article Copyright 2012 by m-idrees
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid