How to Update document in MongoDB

Ratings:
(4)
Views: 0
Banner-Img
Share this blog:

MongoDB

Updating Documents

Once a document is stored in the database, it can be changed using the update method. update takes two parameters: a query document, which locates documents to update, and a modifier document, which describes the changes to make to the documents found.

Updates are atomic: if two updates happen at the same time, whichever one reaches the server first will be applied, and then the next one will be applied. Thus, conflicting updates can safely be sent in rapid-fire succession without any documents being corrupted: the last update will “win.”

Document Replacement

The simplest type of update fully replaces a matching document with a new one. This can be useful to do a dramatic schema migration. For example, suppose we are making major changes to a user document, which looks like the following:

{
"_id" : ObjectId("4b2b9f67a1f631733d917a7a"),
"name" : "joe",
"friends" : 32,
"enemies" : 2
}

We want to change that document into the following:

"_id" : ObjectId("4b2b9f67a1f631733d917a7a"),
"username" : "joe",
"relationships" :
{
"friends" : 32,
"enemies" : 2
}
}

We can make this change by replacing the document using an update:

var joe = db.users.findOne({"name" : "joe"});
joe.relationships = {"friends" : joe.friends, "enemies" : joe.enemies};{
"friends" : 32,
"enemies" : 2
}
joe.username = joe.name;
"joe"
delete joe.friends;
true
delete joe.enemies;
true >
delete joe.name;
true >
db.users.update({"name" : "joe"}, joe);

Now, doing a find One shows that the structure of the document has been updated. A common mistake is matching more than one document with the criteria and then create a duplicate "_id" value with the second parameter. The database will throw an error for this, and nothing will be changed. For example, suppose we create several documents with the same "name", but we don’t realize it:

db.people.find()
{"_id" : ObjectId("4b2b9f67a1f631733d917a7b"), "name" : "joe", "age" : 65},
{"_id" : ObjectId("4b2b9f67a1f631733d917a7c"), "name" : "joe", "age" : 20},
{"_id" : ObjectId("4b2b9f67a1f631733d917a7d"), "name" : "joe", "age" : 49},

Now, if it’s Joe #2’s birthday, we want to increment the value of his "age" key, so we might say this:

joe = db.people.findOne({"name" : "joe", "age" : 20});
{
"_id" : ObjectId("4b2b9f67a1f631733d917a7c"),
"name" : "joe",
"age" : 20
}
joe.age++;
db.people.update({"name" : "joe"}, joe);

E11001 duplicate key on update

What happened? When you call update, the database will look for a document matching {"name" : "joe"}. The first one it finds will be the 65-year-old Joe. It will attempt to replace that document with the one in the joe variable, but there’s already a document in this collection with the same "_id". Thus, the update will fail, because "_id" values must be unique. The best way to avoid this situation is to make sure that your update always specifies a unique document, perhaps by matching on a key like "_id"

Using Modifiers

Usually only certain portions of a document need to be updated. Partial updates can be done extremely efficiently by using atomic update modifiers. Update modifiers are special keys that can be used to specify complex update operations, such as altering, adding, or removing keys, and even manipulating arrays and embedded documents.

Suppose we were keeping website analytics in a collection and wanted to increment a counter each time someone visited a page. We can use update modifiers to do this increment atomically. Each URL and its number of page views is stored in a document that looks like this:

{
"_id" : ObjectId("4b253b067525f35f94b60a31"),
"url" : "www.example.com",
"pageviews" : 52
}

Every time someone visits a page, we can find the page by its URL and use the "$inc" modifier to increment the value of the "pageviews" key.

> db.analytics.update({"url" : "www.example.com"},
... {"$inc" : {"pageviews" : 1}})
Now, if we do a find, we see that "pageviews" has increased by one.
> db.analytics.find()
{
"_id" : ObjectId("4b253b067525f35f94b60a31"), "url" : "www.example.com",
"pageviews" : 53
}

Perl and PHP programmers are probably thinking that any character would have been a better choice than $. Both of these languages use $ as a variable prefix and will replace $-prefixed strings with their variable value in double-quoted strings. However, MongoDB started out as a JavaScript database, and $ is a special character that isn’t interpreted differently in JavaScript, so it was used. It is an annoying historical relic from MongoDB’s primordial soup.

There are several options for Perl and PHP programmers. First, you could just escape the $: "\$foo". You can use single quotes, which don’t do variable interpolation: '$foo'. Finally, both drivers allow you to de-fine your own character that will be used instead of $. In Perl, set $MongoDB::BSON::char, and in PHP set mongo.cmd_char in php.ini to =, :, ?, or any other character that you would like to use instead of $. Then, if you choose, say, ~, you would use ~inc instead of \$inc and ~gt instead of \$gt.

Good choices for the special character are characters that will not naturally appear in key names (don’t use _ or x) and are not characters that have to be escaped themselves, which will gain you nothing and be con-fusing (such as \ or, in Perl, @).

Getting started with the "$set" modifier

"$set" sets the value of a key. If the key does not yet exist, it will be created. This can be handy for updating schema or adding user-defined keys. For example, suppose you have a simple user profile stored as a document that looks something like the following:

> db.users.findOne()
{
"_id" : ObjectId("4b253b067525f35f94b60a31"), "name" : "joe",
"age" : 30, "sex" : "male",
"location" : "Wisconsin"
}

This is a pretty bare-bones user profile. If the user wanted to store his favorite book in his profile, he could add it using "$set":

> db.users.update({"_id" : ObjectId("4b253b067525f35f94b60a31")},
... {"$set" : {"favorite book" : "war and peace"}})
Now the document will have a “favorite book” key:
> db.users.findOne()
{
"_id" : ObjectId("4b253b067525f35f94b60a31"), "name" :

When using modifiers, the value of "_id" cannot be changed. (Note that "_id" can be changed by using whole-document replacement.) Values for any other key, including other uniquely indexed keys, can be modified.

"joe",
"age" : 30, "sex" : "male",
"location" : "Wisconsin", "favorite book" : "war and peace"
}

If the user decides that he actually enjoys a different book, "$set" can be used again to change the value:

> db.users.update({"name" : "joe"},
... {"$set" : {"favorite book" : "green eggs and ham"}})

"$set" can even change the type of the key it modifies. For instance, if our fickle user decides that he actually likes quite a few books, he can change the value of the “favorite book” key into an array:

If the user realizes that he actually doesn’t like reading, he can remove the key altogether with "$unset":

Now the document will be the same as it was at the beginning of this example.

> db.users.update({"name" : "joe"},
... {"$unset" : {"favorite book" : 1}})

Now the document will be the same as it was at the beginning of this example.

Interested in mastering Mongo DB Training?
Learn more about Mongo DB Tutorial in this blog post.

You can also use "$set" to reach in and change embedded documents:

>db.blog.posts.findOne()
{
"_id" : ObjectId("4b253b067525f35f94b60a31"), "title" : "A Blog Post",
"content" : "...", "author" : {
"name" : "joe",
"email" : "joe@example.com"
}
}
>db.blog.posts.update({"author.name" : "joe"}, {"$set" : {"author.name" : "joe schmoe"}})
>db.blog.posts.findOne()
{
"_id" : ObjectId("4b253b067525f35f94b60a31"), "title" : "A Blog Post",
"content" : "...", "author" : {
"name" : "joe schmoe", "email" : "joe@example.com"
}
}

You must always use a $ modifier for adding, changing, or removing keys. A common error people often make when starting out is to try to set the value of "foo" to "bar" by doing an update that looks like this:

> db.coll.update(criteria, {"foo" : "bar"})

This will not function as intended. It actually does a full-document replacement, re-placing the matched document with {"foo" : "bar"}. Always use $ operators for modifying individual key/value pairs.

You liked the article?

Like: 0

Vote for difficulty

Current difficulty (Avg): Medium

EasyMediumHardDifficultExpert
IMPROVE ARTICLEReport Issue

About Author

Authorlogo
Name
TekSlate
Author Bio

TekSlate is the best online training provider in delivering world-class IT skills to individuals and corporates from all parts of the globe. We are proven experts in accumulating every need of an IT skills upgrade aspirant and have delivered excellent services. We aim to bring you all the essentials to learn and master new technologies in the market with our articles, blogs, and videos. Build your career success with us, enhancing most in-demand skills in the market.

Stay Updated
Get stories of change makers and innovators from the startup ecosystem in your inbox