Introduction to MongoDb with .NET part 11: various other update operations

Introduction

In the previous post we started looking into how updates are performed in the MongoDb client. We saw the update function in action with a number of examples. The most basic usage of update is cumbersome in the client as it really only replaces the existing document(s) with a new one. Fortunately there are various $ operators that let us update a single property of a document. We also saw the role of the “multi” argument. If set to true then the update function will update every single document that matches the search criteria. Otherwise only the first matching document will be updated.

In this post we’ll look into various other operations related to updates.

Remove a property completely

The $unset operator is the opposite of $set which we saw in action in the previous post. I don’t want to remove any property from our demo databases “restaurants” and “zipcodes”. I’ll reuse the small people collection here which we built earlier. Every document has a property called “language”. Let’s remove it for Mary:

db.people.update({"name" : "mary"}, {$unset: {"language" : 1}});

Here’s Mary:

{ "_id" : ObjectId("57055d9bb98ee40de4038250"), "name" : "mary", "sport" : "football", "points" : 5 }

In fact we can remove the language property from every document with an empty search term:

db.people.update({}, {$unset: {"language" : 1}}, {multi : true});

The language property of all documents in the people collection has been removed.

Array-related updates

For these examples let’s add an array field to every document in the people collection first:

db.people.update({}, {$set : {"foods" : ["fish", "chips", "chololate"]}}, {multi: true});

We’ve just added a new array property to every document in the people collection and initialised it to the same 3 items.

Arrays and array elements can be updated in various ways in MongoDb. Let’s go through them one by one.

The $set operator can be used to update an individual element in an array by its index where the index is 0-based. E.g. Susan doesn’t like fish any more and we know that fish has the index 1 in every array. We’ll change it to lamb:

db.people.update({"name" : "susan"}, {$set : {"foods.1" : "lamb"}});

Note the dot-notation with an index after the name of the array property. Here’s Susan:

{ "_id" : ObjectId("57055daeb98ee40de4038251"), "name" : "susan", "sport" : "racketball", "points" : 22, "foods" : [ "fish", "lamb", "chololate" ] }

What happens if we provide an index that is out of bounds like here?

db.people.update({"name" : "susan"}, {$set : {"foods.6" : "lamb"}});

MongoDb resolves this by adding nulls to the missing positions:

{ "_id" : ObjectId("57055daeb98ee40de4038251"), "name" : "susan", "sport" : "racketball", "points" : 22, "foods" : [ "fish", "lamb", "chololate", null, null, null, "lamb" ] }

The $push operator lets us add a new item to the end of the array:

db.people.update({"name" : "abdul"}, {$push : {"foods" : "rice"}});

Here’s Abdul:

{ "_id" : ObjectId("57055dcab98ee40de4038252"), "name" : "abdul", "sport" : "tennis", "points" : 13, "foods" : [ "fish", "chips", "chololate", "rice" ] }

We can pop an item from the beginning or the tail of the array by the $pop operator and an integer argument. 1 will pop the rightmost and -1 the leftmost element:

db.people.update({"name" : "kelly"}, {$pop : {"foods" : -1}});
{ "_id" : ObjectId("57055e0fb98ee40de4038253"), "name" : "kelly", "sport" : "tennis", "points" : 5, "foods" : [ "chips", "chololate" ] }

We can add multiple elements at once with the $pushAll operator:

db.people.update({"name" : "kelly"}, {$pushAll : {"foods" : ["pasta", "pizza", "falafel"]}});
{ "_id" : ObjectId("57055e0fb98ee40de4038253"), "name" : "kelly", "sport" : "tennis", "points" : 5, "foods" : [ "chips", "chololate", "pasta", "pizza", "falafel" ] }

We can also remove elements by value with the $pull operator. We’ll remove fish from Kelly’s foods array:

 db.people.update({"name" : "kelly"}, {$pull : {"foods" : "fish"}});
{ "_id" : ObjectId("57055e0fb98ee40de4038253"), "name" : "kelly", "sport" : "tennis", "points" : 5, "foods" : [ "chips", "chololate", "pasta", "pizza", "falafel" ] }

I’ve actually just noticed that I have a typo on chocolate. We can easily update it:

db.people.update({}, {$pull : {"foods" : "chololate"}}, {multi : true})
db.people.update({}, {$push : {"foods" : "chocolate"}}, {multi : true})

Let’s also remove all null values from the foods array:

db.people.update({}, {$pull : {"foods" : null}}, {multi : true})

We also have a $pullAll operator to remove multiple items at once. Only those items will be removed from the array that figure there of course:

db.people.update({"name" : "kelly"}, {$pullAll : {"foods" : ["pasta", "pizza", "tacos"]}})

Pasta and pizza will be removed from Kelly’s foods array, tacos will be ignored obviously.

The $addToSet operator is very useful if we want to hold only unique values in an array. E.g. the foods array should probably not hold duplicated items. So $addToSet will add the items to an array only if it doesn’t contain one yet:

db.people.update({"name" : "kelly"}, {$addToSet : {"foods" : ["pasta", "pizza", "falafel", "chips"]}})

Only pasta and pizza will be added to Kelly’s foods array as it already contains falafel and chips.

Upserts

To wrap up this post and updates in general we’ll look at upserts. An upsert is a combination of update and insert. It’s quite a common requirement that if an object is supplied to an update operation then if there’s already an item by those properties then it’s updated otherwise a new one is inserted. Upserts can be performed using the “upsert” operator much the same way as we attached the multi operator to the update query. Here’s an example where an existing item Abdul will have its sport property updated to cricket:

db.people.update({"name" : "abdul"}, {$set : {"sport" : "cricket"}}, {upsert : true})

On the other hand if we try to update the sport property of a nonexistent document, like here…:

db.people.update({"name" : "andrew"}, {$set : {"sport" : "swimming"}}, {upsert : true})

…then we’ll get a different response type from the server:

WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : ObjectId("570ff0b4ce1104160e789021")
})

The upserted count is 1. Here’s Andrew:

{ "_id" : ObjectId("570ff0b4ce1104160e789021"), "name" : "andrew", "sport" : "swimming" }

Those were the main features of updates in MongoDb. In the next post we’ll look at deletions.

You can view all posts related to data storage on this blog here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

My goal with this blog is to offend everyone in the world at least once with my words… so no one has a reason to have a heightened sense of themselves. We are all ignorant, we are all found wanting, we are all bad people sometimes.

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: