MongoDB update with condition

I'm trying to update some field in my collection depending on a condition.

I want to set field active to true if the condition is true and to false otherwise

This is update without condition

db.consent.update(
{}, //match all
{
    $set: {
        "active": true
    }
}, 
{
    multi: true,
}

)

I would like to add a condition to update like this:

db.consent.update(
{},
$cond: {
    if: {

        $eq: ["_id", ObjectId("5714ce0a4514ef3ef68677fd")]

    },
    then: {
        $set: {
            "active": true
        }
    },
    else: {
        $set: {
            "active": false
        }
    }
}, 
{
    multi: true,
}

)

According to https://docs.mongodb.org/manual/reference/operator/update-field/ there is no $cond operator for update.

What are my options here to execute this update as a single command?


Solution 1:

Starting Mongo 4.2, db.collection.update() can accept an aggregation pipeline, finally allowing the update/creation of a field based on another field:

// { a: "Hello", b: "World" }
// { a: "Olleh", b: "Dlrow" }
db.collection.update(
  {},
  [ { $set: { active: { $eq: [ "$a", "Hello" ] } } } ],
  { multi: true }
)
// { a: "Hello", b: "World", active: true  }
// { a: "Olleh", b: "Dlrow", active: false }
  • The first part {} is the match query, filtering which documents to update (in our case all documents).

  • The second part [ { $set: { active: { $eq: [ "$a", "Hello" ] } } } ] is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline). $set is a new aggregation operator and an alias of $addFields. Then any aggregation operator can be used within the $set stage; in our case a conditional equality check on which depends the value to use for the new active field.

  • Don't forget { multi: true }, otherwise only the first matching document will be updated.

Solution 2:

You can't.

Mongo doesn't support combining fields, conditionals etc. in the update statement.


See https://stackoverflow.com/a/56551655/442351 below.