7

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);  

1 Answer 1

10

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}});
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I was afraid it is so, so it means, it's not going to be transactional, right?
@EranMedan: yeah, but there's a workaround. See updated answer.
@SergioTulentsev hi what do you think of this

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.