mongodbpositional-operator

How to toggle a Boolean field in an Array element in MongoDB?


Consider this data

{ 
    "_id" : ..., 
    "array" : [
        { "name" : "value1","flag" : true } ,
        { "name" : "value2","flag" : false }
  ]
}

I would like to toggle the 2nd array element (from false to true)

I know I can update a specific element using the very useful $ positional operator like this:

db.myCollection.update(
    {'array.name':'value2'},
    {
        $set: {
            'array.$.flag':true
        }
    },false,true);  

But is there a way to use the $ positional operator also for the value setting?

e.g. like this?

db.myCollection.update(
    {'array.name':'value2'},
    {
        $set: {
            'array.$.flag':'!array.$.flag' //<--
        }
    },false,true);  

Solution

  • No, it's not possible at the moment. MongoDB doesn't allow expressions in updates that depend on fields in the document. You'll have to get and set in two separate operations.

    However, there's a trick to make it in one operation (and therefore atomic). Instead of a boolean value, have an integer. Then even values will represent false, odd ones - true.

    // get documents with false flag
    db.collection.find({flag: {$mod: [2, 0]}})
    
    // get documents with true flag
    db.collection.find({flag: {$mod: [2, 1]}})
    
    // toggle flag
    db.collection.update(query, {$inc: {flag: 1}});