Update Property in a Nested Array of entities in MongoDB

MongoDB

Many of us would have already used MongoDB for storing data as Documents. However, I come from a world of SQL where everything is stored in Tables following the Normalization process. Hence, anything that can be further broken down, should be considered storing in a separate table.

In the world of MongoDB or rather, No-SQL, we do not have anything like that. Here, the more connected the data is supposed to have, the more chances of storing them together makes sense. Let’s look at the below example:

{
    "_id":"d5ebb427",
    "name":"Anubhav Ranjan",
    "email":"[email protected]",
    "subscriptions":[
        {
            "subscriptionId":"1abc",
            "showId":"d060b8ca",
            "notificationEnabled":true
        },
        {
            "subscriptionId":"2abc",
            "showId":"d060b8cb",
            "notificationEnabled":true
        }
    ]
}

Let’s consider the code snippet above. I have an object User having Two Subscriptions. Now I want to make one of the Subscriptions as false. This should be done using C#.

Let’s see how this can be achieved using Mongo shell

db.users.find({ _id: "d5ebb427", "subscriptions.subscriptionId":"1abc"});

db.users.update({ _id: "d5ebb427", "subscriptions.subscriptionId":"1abc"}, { $set: {"subscriptions.$.notificationEnabled": false}});

Let’s go ahead and check out the C# implementation

// C# Mongo Schema
public class User
{
    [BsonId]
    public string Id { get; set; }
    [BsonElement("name")]
    public string Name { get; set; }
    [BsonElement("email")]
    public string Email { get; set; }
    [BsonElement("subscriptions")]
    public Subscription[] Subscriptions { get; set; }
}


public class Subscription
{
    [BsonElement("subscriptionId")]
    public string SubscriptionId{ get; set; }
    [BsonElement("showId")]
    public string ShowId { get; set; }
    [BsonElement("notificationEnabled")]
    public bool NotificationEnabled { get; set; }
}

In order to do this, we are using the positional $ operator.
As per the MongoDB docs, The positional $ operator identifies an element in an array to update without explicitly specifying the position of the element in the array.

var filter = Builders.Filter;
var userSubscriptionFilter = filter.And(
    filter.Eq(u => u.Id, id),
    filter.ElemMatch(u => u.Subscriptions, s => s.SubscriptionId == subId)
);
// Find User with Id and Subscription Id
var user = await usersCollection.Find(userSubscriptionFilter).SingleOrDefaultAsync();

// Update using the positional operator
var update = Builders.Update;
var subscriptinonSetter = update.Set("subscriptions.$.notificationEnabled", false);
var updateResult = await usersCollection.UpdateOneAsync(userSubscriptionFilter, subscriptinonSetter);

After further reading, I have even found that you can change the line from this:

var subscriptinonSetter = update.Set("subscriptions.$.notificationEnabled", false);

to this:

var subscriptinonSetter = update.Set(s =>  s.Subscriptions[-1].NotificationEnabled, false);

Happy Coding!

Find 10 Memory Consuming Processes in Ubuntu

Let’s first talk about the reason I started looking for this. I have a couple of services running in Ubuntu including DBs like MySQL, MongoDB, etc. along with running nGinx and other services.

However, sometimes, I noticed that the memory consumption goes upwards and it’s wise to know which process could be responsible for this.

I decided to look into this using the ps command

ps -eo pmem,pcpu,pid,args | tail -n +2 | sort -rnk 1 | head
Output for the above ps command

Let’s look at the arguments provided:

psCurrent process snapshot report
-eSelect all processes. Identical to -A.
-oformat is a single argument in the form of a blank-separated or comma-separated list, which offers a way to specify individual output columns.
pmemthe ratio of the process’s resident set size to the physical memory on the machine, expressed as a percentage.
pcpuCPU utilization of the process in the “##.#” format. Currently, it is the CPU time used divided by the time the process has been running (cputime/real time ratio), expressed as a percentage.
pidA number representing the process ID
argsCommand with all its arguments as a string.
tail -n +2Output lines starting to the second line
sort -rnk 1r (reverse) n(numeric sort) by column 1 i.e., pmem
headOutput the first 10 lines
Based on man ps

Hope it helps!