Pluralsight Logo
Author avatar

Praveen Kumar

Author badge Author

Introduction to MongoDB - Records and Values

Praveen Kumar

Author BadgeAuthor
  • Aug 7, 2018
  • 13 Min read
  • 6,322 Views
  • Aug 7, 2018
  • 13 Min read
  • 6,322 Views
SQL
MongoDB
NoSQL

Getting Set Up

Please read the first guide in this series for more information about setting up MongoDB - Installation, Shell, and Database Management.

Bulk Insertion

Yep, you read that right. Like MySQL, you can also insert many records at a single point in time. The same insert() function takes not only objects but also arrays as input. This time, we will be lazy and create something simple for the next two records.

1
2
3
4
5
6
7
8
9
10
11
12
13
db.students.insert([
  {
    name: "Purushothaman",
    degree: "Management",
    email: "purush@example.com"
  },
  {
    name: "Meaow Meaow",
    degree: "Cat Study",
    email: "meaow@example.com",
    phone: ["9850420420"]
  }
]);
javascript

You can see that the above records are both different. This leads us to the biggest advantage of Document Databases. You don't need a fixed schema for the records and each record can be any valid JavaScript expression.

Changing schema "on the fly" is the biggest advantage of using NoSQL.

Now, let's try executing the above insert query on our database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
> db.students.insert(
...   [
...     {
...       "name": "Purushothaman",
...       "degree": "Management",
...       "email": "purush@example.com"
...     },
...     {
...       "name": "Meaow Meaow",
...       "degree": "Cat Study",
...       "email": "meaow@example.com",
...       "phone": ["9850420420"]
...     },
...   ]
... );
BulkWriteResult({
    "writeErrors" : [ ],
    "writeConcernErrors" : [ ],
    "nInserted" : 2,
    "nUpserted" : 0,
    "nMatched" : 0,
    "nModified" : 0,
    "nRemoved" : 0,
    "upserted" : [ ]
})
>
javascript

You get the output of the BulkWriteResult function, where it says nothing for errors and we have a count of '2' for the inserted records. Let's quickly check our table contents by using find() method.

1
2
3
4
5
> db.students.find();
{ "_id" : ObjectId("592ebe7e8e61243307417cc4"), "name" : "Praveen Kumar", "degree" : "Cloud Computing", "email" : "praveen@example.com", "subjects" : [ { "name" : "Internet Networks", "prof" : "Prof. Awesome Blossom" }, { "name" : "Cloud Computing", "prof" : "Prof. Tech Ninja" }, { "name" : "Web Development", "prof" : "Prof. Chunky Monkey" } ], "phone" : [ "9840035007", "9967728336", "7772844242" ] }
{ "_id" : ObjectId("592ed5818e61243307417cc5"), "name" : "Purushothaman", "degree" : "Management", "email" : "purush@example.com" }
{ "_id" : ObjectId("592ed5818e61243307417cc6"), "name" : "Meaow Meaow", "degree" : "Cat Study", "email" : "meaow@example.com", "phone" : [ "9850420420" ] }
>

We got the three records and each has different schema, which is great! Since there are too many fields, let's make it pretty():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
> db.students.find().pretty();
{
    "_id" : ObjectId("592ebe7e8e61243307417cc4"),
    "name" : "Praveen Kumar",
    "degree" : "Cloud Computing",
    "email" : "praveen@example.com",
    "subjects" : [
        {
            "name" : "Internet Networks",
            "prof" : "Prof. Awesome Blossom"
        },
        {
            "name" : "Cloud Computing",
            "prof" : "Prof. Tech Ninja"
        },
        {
            "name" : "Web Development",
            "prof" : "Prof. Chunky Monkey"
        }
    ],
    "phone" : [
        "9840035007",
        "9967728336",
        "7772844242"
    ]
}
{
    "_id" : ObjectId("592ed5818e61243307417cc5"),
    "name" : "Purushothaman",
    "degree" : "Management",
    "email" : "purush@example.com"
}
{
    "_id" : ObjectId("592ed5818e61243307417cc6"),
    "name" : "Meaow Meaow",
    "degree" : "Cat Study",
    "email" : "meaow@example.com",
    "phone" : [
        "9850420420"
    ]
}
>
javascript

Ah! There we go!

Querying Records

For querying or filtering the fields, we need to pass them as parameter objects in the find() function. One example will be, let's see if I can get the record with Meaow Meaow:

1
2
3
> db.students.find({"name" : "Meaow Meaow"});
{ "_id" : ObjectId("592ed5818e61243307417cc6"), "name" : "Meaow Meaow", "degree" : "Cat Study", "email" : "meaow@example.com", "phone" : [ "9850420420" ] }
>
javascript

And, as usual, our pretty() would return:

1
2
3
4
5
6
7
8
9
10
11
> db.students.find({"name" : "Meaow Meaow"}).pretty();
{
    "_id" : ObjectId("592ed5818e61243307417cc6"),
    "name" : "Meaow Meaow",
    "degree" : "Cat Study",
    "email" : "meaow@example.com",
    "phone" : [
        "9850420420"
    ]
}
>
javascript

This also works for items inside arrays. The find() method does exact matches of the values here. Here is one more example for matching a number within an array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
> db.students.find({"phone": "9840035007"}).pretty();
{
    "_id" : ObjectId("592ebe7e8e61243307417cc4"),
    "name" : "Praveen Kumar",
    "degree" : "Cloud Computing",
    "email" : "praveen@example.com",
    "subjects" : [
        {
            "name" : "Internet Networks",
            "prof" : "Prof. Awesome Blossom"
        },
        {
            "name" : "Cloud Computing",
            "prof" : "Prof. Tech Ninja"
        },
        {
            "name" : "Web Development",
            "prof" : "Prof. Chunky Monkey"
        }
    ],
    "phone" : [
        "9840035007",
        "9967728336",
        "7772844242"
    ]
}
>
javascript

The above command correctly identifies my record and displays it, even though 9840035007 is only one of three numbers present.

Updating Records

The method we use here is db.collection.update(). It takes up two parameters and the first parameter is an object of a key value pair for a match that is present in the records. The next parameter is the content that the first parameter is supposed to be replaced with.

So let's try something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
db.students.update(
  { name: "Praveen Kumar" },
  {
    name: "Praveen Kumar",
    degree: "Cloud Computing MSc",
    email: "praveen@example.net",
    subjects: [
      {
        name: "Internet Networks",
        prof: "Prof. Awesome Blossom"
      },
      {
        name: "Cloud Computing",
        prof: "Prof. Tech Ninja"
      },
      {
        name: "Web Development",
        prof: "Prof. Chunky Monkey"
      }
    ],
    phone: ["9840035007", "9967728336", "7772844242"]
  }
);
javascript

Note 1: You need to give the full object in case of update function, because it makes a replacement of the whole record with the second parameter. If we didn't set the other values, it will just have one record with just two of the items: the email and the degree.

Note 2: Do not find by name, as I just did, if at all possible. There may be many records matching the same parameter, so use something unique like _id.

Trying the above, we get:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> db.students.update({"name": "Praveen Kumar"}, {
...   "name": "Praveen Kumar",
...   "degree": "Cloud Computing MSc",
...   "email": "praveen@example.net",
...   "subjects": [
...     {
...       "name": "Internet Networks",
...       "prof": "Prof. Awesome Blossom"
...     },
...     {
...       "name": "Cloud Computing",
...       "prof": "Prof. Tech Ninja"
...     },
...     {
...       "name": "Web Development",
...       "prof": "Prof. Chunky Monkey"
...     }
...   ],
...   "phone": ["9840035007", "9967728336", "7772844242"]
... });
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
javascript

Voila! Let's see the results:

1
2
3
4
5
{
  "nMatched": 1,
  "nUpserted": 0,
  "nModified": 1
}
javascript

It matched one record and it modified it. There's none upserted (we'll cover this later). This means that there's a possibility that it might match, but not update. Let's run the same command again and see what happens.

Oh dear! It shows the same output. Maybe I was over-enthusiastic.

To see what has changed, we could try to run the find() function along with our pretty pretty() function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
> db.students.find({"phone": "9840035007"}).pretty();
{
    "_id" : ObjectId("592ebe7e8e61243307417cc4"),
    "name" : "Praveen Kumar",
    "degree" : "Cloud Computing MSc",
    "email" : "praveen@example.net",
    "subjects" : [
        {
            "name" : "Internet Networks",
            "prof" : "Prof. Awesome Blossom"
        },
        {
            "name" : "Cloud Computing",
            "prof" : "Prof. Tech Ninja"
        },
        {
            "name" : "Web Development",
            "prof" : "Prof. Chunky Monkey"
        }
    ],
    "phone" : [
        "9840035007",
        "9967728336",
        "7772844242"
    ]
}
>
javascript

Using `$set`

It's a pain to add the whole record again, just to change one single value. The good news is, there's a way around that: using the $set operator. Say we need to change my email to praveen@example.net. All that we need to do is:

1
2
3
4
5
6
7
8
9
10
db.students.update(
  {
    name: "Praveen Kumar"
  },
  {
    $set: {
      email: "praveen@example.net"
    }
  }
);
javascript

Short and sweet! Now let's see the output of the above command.

1
2
3
4
5
6
7
8
9
> db.students.update({
...   "name": "Praveen Kumar"
... }, {
...   $set: {
...     "email" : "praveen@example.net"
...   }
... });
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
javascript

This $set is somewhat similar to our SQL's UPDATE query. When the query is fired, it keeps the already existing value intact and updates the respective fields. Similar to UPDATE, $set shows how many rows the query has affected.

If we see the above result, we can find that the command has matched one and modified one, but not upserted any. If we try to run the same command again, it will give the following result:

1
WriteResult({ nMatched: 1, nUpserted: 0, nModified: 0 });
javascript

Great! Now we know see that matched and modified have different counts. This means, even if you keep sending the same command for update without the $set operator, the modification keeps happening all the time, while the $set operator makes it happen only if there are different values.

Note: $set is more performance efficient, if you are making a lot of updates.

Incrementing Numeric Values

There's another operator that helps us increment numeric values. Consider a record that has some numeric parameter, such as a field called points. points are great because they need to increment frequently. Being lazy, I am going to use the $set function:

1
2
3
4
5
6
7
8
9
10
db.students.update(
  {
    name: "Praveen Kumar"
  },
  {
    $set: {
      points: 15
    }
  }
);
javascript

Executing the above command, we get this:

1
2
3
4
5
6
7
8
9
> db.students.update({
...   "name": "Praveen Kumar"
... }, {
...   $set: {
...     "points" : 15
...   }
... });
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
javascript

And, checking if it has been updated, we fire out the find() command and we get:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
> db.students.find({"phone": "9840035007"}).pretty();
{
    "_id" : ObjectId("592ebe7e8e61243307417cc4"),
    "name" : "Praveen Kumar",
    "degree" : "Cloud Computing MSc",
    "email" : "praveen@example.com",
    "subjects" : [
        {
            "name" : "Internet Networks",
            "prof" : "Prof. Awesome Blossom"
        },
        {
            "name" : "Cloud Computing",
            "prof" : "Prof. Tech Ninja"
        },
        {
            "name" : "Web Development",
            "prof" : "Prof. Chunky Monkey"
        }
    ],
    "phone" : [
        "9840035007",
        "9967728336",
        "7772844242"
    ],
    "points" : 15
}
>
javascript

Excellent. We have a points field in my record with a value of 15.

That entire process should be clear by now. If something is unclear, look back at the previous section of the guide and/or fire off a question for additional clarity.

Moving on, I complete this article, thereby earning 5 more points. This condition can be produced with one small change:

1
2
3
4
5
6
7
8
9
10
db.students.update(
  {
    name: "Praveen Kumar"
  },
  {
    $inc: {
      points: 5
    }
  }
);
javascript

As you can see, changing $set to $inc, makes the difference. This is similar to using the augmented assignment operator += in standard languages, rather than the assignment operator =.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
> db.students.update({
...   "name": "Praveen Kumar"
... }, {
...   $inc: {
...     "points" : 5
...   }
... });
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.students.find({"phone": "9840035007"}).pretty();
{
    "_id" : ObjectId("592ebe7e8e61243307417cc4"),
    "name" : "Praveen Kumar",
    "degree" : "Cloud Computing MSc",
    "email" : "praveen@example.com",
    "subjects" : [
        {
            "name" : "Internet Networks",
            "prof" : "Prof. Awesome Blossom"
        },
        {
            "name" : "Cloud Computing",
            "prof" : "Prof. Tech Ninja"
        },
        {
            "name" : "Web Development",
            "prof" : "Prof. Chunky Monkey"
        }
    ],
    "phone" : [
        "9840035007",
        "9967728336",
        "7772844242"
    ],
    "points" : 20
}
>
javascript

Wow, that was an easy increment for me from 15 to 20. Clearly, using $inc is a great way to increment numeric values.

Additional Reading

Please read the next guide in this series for more information about MongoDB - Editing Records.

1