0

See example below (json format from mongochef). I need to add a new field to each element in our collection called isReadOnly (bool). How would I do this? I can easily add it to the root of the document but battling to do it within each array element.

{ 
"_id" : "fda42f22-0fa4-4e4a-94bf-245b1124c8b9", 
"_t" : "FullConfiguration", 
"DeviceConfigName" : "Illinois", 
"Elements" : [
    {
        "_t" : "NumberConfigurationElement", 
        "AsciiConfigNumber" : NumberInt(10), 
        "DataType" : NumberInt(1), 
        "ByteOffset" : NumberInt(0), 
        "Name" : "alcohol_limit", 
        "Description" : "The alcohol limit of the device (ug/l)", 
        "AckResponse" : "HT-CONFG,010,00119", 
        "DevicePart" : NumberInt(1), 
        "Value" : NumberInt(119), 
        "DefaultValue" : NumberInt(119), 
        "Min" : NumberInt(50), 
        "Max" : NumberInt(500)
    }, .....

3 Answers 3

2

You can do it like this(if your collection is called 'coll'):

db.coll.find().forEach(function(e) {
    var t = e.Elements;
    t.forEach(function(e) {
        e.isReadOnly=false
    });
    db.coll.update({ _id : e._id }, { $set: { Elements : t } } );
})
Sign up to request clarification or add additional context in comments.

2 Comments

This pushes an additional document of { isReadOnly: false } to the existing elements array, not to each document inside the array. There is an open issue on the MongoDB JIRA about this, I think the only way to do this is inside JavaScript using Mongoose or another MongoDB driver.
@dyouberg there is better way to do this and you probably don't want to iterate the cursor like that as shown in the answer because there is a possibility for race condition and remember Murphy's law
0

@Styvane , this is what I came up with, it still seems a bit hacky.

var query = {
    Elements: {
        $elemMatch: {
            _t: { $exists: true },
            isReadOnly: { $exists: false }
        }
    }
};

while (db.collection.find(query).count() > 0) {
    db.collection.update(
        query, 
        { $set: { "Elements.$.isReadOnly": true } }
    );    
}

1 Comment

This also is not good. This is factually correct in MongoDB 2.4 and even then, you can just iterate the cursor but instead a snapshot of the curor. The best way to do this is with bulk operation
0

@David I've working solution with MongoDB 3.6+.

db.collection.update({},
    { $set: { "Elements.$[].isReadOnly": false } }, { multi: true }
)

This command will add isReadOnly = false field in all Element array field of documents.

The $position modifier specifies the location in the array at which the $push operator inserts elements. Without the $position modifier, the $push operator inserts elements to the end of the array. See $push modifiers for more information.

More details you can find on position operator docs

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.