chnging
chnging

Reputation: 775

Updating a number of objects in a nested array

Lets say we have this document:

{
    "_id" : ObjectId("4faaba123412d654fe83hg876"),
    "items" : [
            {
                    "name" : "item_one",
                    "bought" : true
            },
            {
                    "name" : "my_item",
                    "bought" : true
            },
            {
                    "name" : "my_item_three",
                    "bought" : true
            }
    ]
}

For example how can I modify the first 2 objects of the array and set their "bought" to false. Or in other words how could I change properties of the first n objects.

I thought I could first do a db.findOne() with this ID than take the items and use a function that will change the values and then set the whole item to this new array that this function returns.

That would probably do the work but is there a faster and nicer method? Is there a way to do it if I know the number of objects I want to change, so it will not be n but 5 for example.

Upvotes: 2

Views: 44

Answers (2)

chridam
chridam

Reputation: 103365

If you know the number of objects you want to update beforehand then you could take advantage of the dot notation in your update to access the elements of an array with a loop:

var id = ObjectId("4faaba123412d654fe83hg876");

// Iterate and update using the update query object 
for(var i=0; i<n; i++){ 
    var update = { "$set": {} };
    // set the update query object
    update["$set"]["items."+i.toString()+".bought"] = false;
    db.collection.update({"_id": id}, update, {"upsert": false, "multi": true});
}

-- EDIT --

This can also be done in one atomic update, given that you create the update object prior to the update, something like this

var update = { "$set": {} };
for(var i=0; i<n; i++){ 
    // set the update query object
    update["$set"]["items."+i.toString()+".bought"] = false;    
}

db.collection.update({"_id": id}, update, {"upsert": false, "multi": true});

Check the demo below

var update = { "$set": {} };
for(var i=0; i<5; i++){ 
    // set the update query object
    update["$set"]["items."+i.toString()+".bought"] = false;    
}

pre.innerHTML = JSON.stringify(update);
<pre id="pre"></pre>

Upvotes: 1

Tariq
Tariq

Reputation: 2871

You can loop over the nth objects you need and set the bought to false by using the '=':

for(var i=0; i < n_times; i++){  
    my_object.items[i].bought = false;
}

Upvotes: 3

Related Questions