Update with upsert: MongoDB


Lets learn to use upsert option with update() method.

upsert basically inserts document into the collection, if there is no matching document found in the collection. If there is a match found, then the document simply gets updated – in which case upsert option will not have any effect on the selected document.

update with upsert mongodb

test database, names collection

1
2
3
4
5
6
7
8
9
10
11
12
13
> db.names.find().pretty()
{
        "_id" : ObjectId("53c6392a2eea8062e084cb57"),
        "Company" : "Google",
        "Product" : "Nexus",
        "No" : 1
}
{
        "_id" : ObjectId("53c639392eea8062e084cb58"),
        "Company" : "Apple",
        "Product" : "iPhone",
        "No" : 2
}

There are 2 documents inside “names” collection, with _id, Company, Product and No as its fields.

Update with upsert: MongoDB


[youtube https://www.youtube.com/watch?v=ZQjNHjVv_W8]

YouTube Link: https://www.youtube.com/watch?v=ZQjNHjVv_W8 [Watch the Video In Full Screen.]



update() method, with $set operator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> db.names.update({"Company": "Apple"}, {$set: {"Product": "Mac"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
 
> db.names.find().pretty()
{
        "_id" : ObjectId("53c6392a2eea8062e084cb57"),
        "Company" : "Google",
        "Product" : "Nexus",
        "No" : 1
}
{
        "_id" : ObjectId("53c639392eea8062e084cb58"),
        "Company" : "Apple",
        "Product" : "Mac",
        "No" : 2
}

We select second document using “Company” – “Apple“. Here, the “Product” field value gets updated from iPhone to Mac.

Related Read: Update with SET Operator: MongoDB

No Match Found for Updation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> db.names.update({"Company": "Xiaomi"}, {$set: {"Product": "Mi3", "No": 3}});
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
 
> db.names.find().pretty()
{
        "_id" : ObjectId("53c6392a2eea8062e084cb57"),
        "Company" : "Google",
        "Product" : "Nexus",
        "No" : 1
}
{
        "_id" : ObjectId("53c639392eea8062e084cb58"),
        "Company" : "Apple",
        "Product" : "Mac",
        "No" : 2
}

Since, there is no matching “Company” called Xiaomi in “names” collection, there will be no matching document, hence no modification of document.

updation with upsert option

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
> db.names.update({"Company": "Xiaomi"}, 
                  {$set: {"Product": "Mi3", "No": 3}},
                  {upsert: true});
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : ObjectId("53c63b26b003603dfdcf8c52")
})
 
> db.names.find().pretty()
{
        "_id" : ObjectId("53c6392a2eea8062e084cb57"),
        "Company" : "Google",
        "Product" : "Nexus",
        "No" : 1
}
{
        "_id" : ObjectId("53c639392eea8062e084cb58"),
        "Company" : "Apple",
        "Product" : "Mac",
        "No" : 2
}
{
        "_id" : ObjectId("53c63b26b003603dfdcf8c52"),
        "Company" : "Xiaomi",
        "Product" : "Mi3",
        "No" : 3
}

Observe the 3rd argument of update() method – upsert: true. In this case, since there is no matching document found inside the “names” collection, for “Company” Xiaomi, it inserts the document with all the fields and values specified in the update command. i.e., Company: Xiaomi, Product: Mi3, No: 3

unintentional modification of data with upsert

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
> db.names.update({"No": {$gt: 3}}, 
                  {$set: {"Product": "Glass", "No": 4}}, 
                  {upsert: true});
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : ObjectId("53c63bd1b003603dfdcf8c53")
})
 
> db.names.find().pretty()
{
        "_id" : ObjectId("53c6392a2eea8062e084cb57"),
        "Company" : "Google",
        "Product" : "Nexus",
        "No" : 1
}
{
        "_id" : ObjectId("53c639392eea8062e084cb58"),
        "Company" : "Apple",
        "Product" : "Mac",
        "No" : 2
}
{
        "_id" : ObjectId("53c63b26b003603dfdcf8c52"),
        "Company" : "Xiaomi",
        "Product" : "Mi3",
        "No" : 3
}
{
        "_id" : ObjectId("53c63bd1b003603dfdcf8c53"),
        "Product" : "Glass",
        "No" : 4
}

We have documents which has values 1, 2 and 3 for the field “No”. But in above command the condition is to select documents which has “No” value above 3 – which results in 0 documents being selected. But since we have “upsert: true” as the third argument of update() method, the “field: value” – “Product: Glass” and “No: 4” gets inserted into the “names” collection. So we need to take proper care of our commands and conditions – so that unintentional insertion of data or document can be avoided.

upsert effect on existing data/document

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
> db.names.update({"No": 4}, 
                  {$set: {"Company": "Sony", "Product": "Smart Watch"}}, 
                  {upsert: true});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
 
> db.names.find().pretty()
{
        "_id" : ObjectId("53c6392a2eea8062e084cb57"),
        "Company" : "Google",
        "Product" : "Nexus",
        "No" : 1
}
{
        "_id" : ObjectId("53c639392eea8062e084cb58"),
        "Company" : "Apple",
        "Product" : "Mac",
        "No" : 2
}
{
        "_id" : ObjectId("53c63b26b003603dfdcf8c52"),
        "Company" : "Xiaomi",
        "Product" : "Mi3",
        "No" : 3
}
{
        "_id" : ObjectId("53c63bd1b003603dfdcf8c53"),
        "Product" : "Smart Watch",
        "No" : 4,
        "Company" : "Sony"
}

In this case, there is a document inside the collection which has “No”: 4. So the upsert option will not have any effect on the selected data/document – it simply gets updated with the field values specified in the second argument of update() method. i.e., the document with “No”: 4 is selected and the “Company”: “Sony”, “Product”: “Smart Watch” gets added to the existing document.

Leave a Reply

Your email address will not be published. Required fields are marked *