Normal updates do not automatically insert objects because they incur a cost when they need to determine whether an object exists. If you know that an object exists, then a normal update()
is efficient; insert()
is better if you know that a document does not already exist. When you want a combination of updating an object if it exists and inserting it if it does not, you use upsert
.
To implement upsert
, you include the upsert:true
option in the update()
method’s options
parameter. This tells the request to try to update the object if it exists and to insert the object specified if it doesn’t already exist.
Listing 14.6 shows how to use upsert
with the update()
method. The update()
in lines 9–12 creates the object because it does not exist. Then line 17 retrieves the _id
value of the inserted document and uses it in the query of the update()
in lines 18–21 to ensure that an existing document will be found and updated. Figure 14.6 shows the output of the code in Listing 14.6. Notice that initially no documents match the descriptor and then after the first update, the document is inserted, and then it’s modified after the second update.
Note
To run the code in this exercise, please run the code in exercise 14.1 first to reset the data that may have changed by running other exercises in this chapter.
01 var MongoClient = require('mongodb').MongoClient;
02 MongoClient.connect("mongodb://localhost/", function(err, db) {
03 var myDB = db.db("astro");
04 myDB.collection("nebulae", function(err, nebulae){
05 nebulae.find({type:"diffuse"}, function(err, items){
06 items.toArray(function(err, itemArr){
07 console.log("Before Upsert: ");
08 console.log(itemArr);
09 nebulae.update({type:"diffuse"},
10 {$set: {ngc:"NGC 3372", name:"Carina",
11 type:"diffuse",location:"Carina"}},
12 {upsert:true, w:1,forceServerObjectId:false},
13 function(err, results){
14 nebulae.find({type:"diffuse"}, function(err, items){
15 items.toArray(function(err, itemArr){
16 console.log("After Upsert 1: ");
17 console.log(itemArr);
18 var itemID = itemArr[0]._id;
19 nebulae.update({_id:itemID},
20 {$set: {ngc:"NGC 3372", name:"Carina",
21 type:"Diffuse",location:"Carina"}},
22 {upsert:true, w:1}, function(err, results){
23 nebulae.findOne({_id:itemID}, function(err, item){
24 console.log("After Upsert 2: ");
25 console.log(item);
26 db.close();
27 });
28 });
29 });
30 });
31 });
32 });
33 });
34 });
35 });