开发者

How do I update/set/unset a key in embedded document/array in MongoDB?

开发者 https://www.devze.com 2023-04-13 09:00 出处:网络
I am trying to unset all values in a document that\'s embedded in an array. Let\'s say I have a collection coll with array things,开发者_开发技巧 containing a value myval. I want to unset myval.This l

I am trying to unset all values in a document that's embedded in an array. Let's say I have a collection coll with array things,开发者_开发技巧 containing a value myval. I want to unset myval. This looks like:

{ things: [{ myval: 1 }, { myval: 2 }] }

I've tried both

db.coll.update({}, {$unset: {'things.myval': 1}})

and

db.coll.things.update({}, {$unset: {'myval': 1}})

Neither of these work. I can't find any documentation online describing how to do this.


I came across this and was frustrated to see the only was to do this was using a nested forEach. So after some searching I found another way! Since mongo version 3.6 there is a all positional operator ($[]) (version 3.6 was introduced way after this question was asked... and even after it was last active, BUT incase anyone else comes across this)

To remove the column myval from the first embedded document to match, do this:

db.coll.update(
  {things: {'$exists': true}},
  {$unset: {'things.$[].myval': 1}}
)

or if you want to remove it from all document that match use the updateMany

db.coll.updateMany(
  {things: {'$exists': true}},
  {$unset: {'things.$[].myval': 1}}
)

The $unset will only edit it if the value exists but it will not do a safe navigation (i.e. it wont check it things exists first) so the exists is needed on the embedded document/array.


You can remove a value from an "array" using the $pull operator:

db.coll.update({}, {$pull: {'things': {'myval': 1}}});

Also have a look at the documentation of $pull:

http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull


Should work with your first approach according with the official documentation:

db.coll.update({}, {$unset: {'things.myval': 1}})

But that doesn't work for me to. So, the solution I found, applied to your example was:

db.coll.find().forEach(function(o) {
    for(var i=0; i<o.things.length; i++) {
        var unset = {};
        unset["things." + i + ".myval"] = "";
        db.coll.update( { "_id": o._id  }, { "$unset": unset } );
    }
})

Or with a more functional style:

db.coll.find().forEach(function(o) {
    o.things.forEach(function(t, i) {
        var unset = {};
        unset["things." + i + ".myval"] = "";
        db.coll.update( { "_id": o._id  }, { "$unset": unset } );
    })
})


It can't work because the {}-empty selector selects more than one documents, and update normally try to update a single document.In order to make it work, use the multi flag to tell mongo update that more than one document is comin.

multi - indicates if all documents matching criteria should be updated rather than just one. Can be useful with the $ operators below.

db.coll.update({}, {$unset: {'things.myval': 1}},false,true)

or

db.coll.update({}, {$pull: {'things': {'myval': 1}}},false,true)

Try either one and will see which one works, but you have to use multi param in both

0

精彩评论

暂无评论...
验证码 换一张
取 消