[SERVER-1088] set a value only if not already set Created: 04/May/10  Updated: 06/Dec/22  Resolved: 29/Jun/19

Status: Closed
Project: Core Server
Component/s: Write Ops
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: pablo platt Assignee: Backlog - Query Team (Inactive)
Resolution: Won't Do Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Query
Participants:

 Description   

I suggest a feature that allows to set a value to a field only if it is not already defined.
This could be similar to $addToSet and might be called $init:

db.users.insert(

{uid: 15, name: "myname"}

)
db.users.update(

{uid: 15}

, { $init :

{ status : "offline" }

}
// the status field wasn't set so it is initialized

{uid: 15, name: "myname", status: "offline"}

db.users.update(

{uid: 15}

, { $set :

{ status : "online" }

}
db.users.update(

{uid: 15}

, { $init :

{ status : "offline" }

}
// no effect because the status field was already set.

{uid: 15, name: "myname", status: "online"}

Note that $not and $exists won't help in case you want to set some fields and init others:
db.users.update(

{uid: 15}

, { $init :

{status : "offline" }

, $set:

{age: 23}

}



 Comments   
Comment by Asya Kamsky [ 29/Jun/19 ]

SERVER-40381 implemented support for aggregation expressions to specify update for 4.2. 

You can see some examples here.

This can be done by setting the field conditionally using various aggregation array expressions.

db.c.update({}, [
      {$set:{newField:{$cond:{
            if: {$eq:[ {$type:"$newField"} ,  "missing" ]},
            then: <newValue>,
            else: "$newField"    // keep existing value
      }}}}
]);

Even simpler, if you consider null is the same as missing you can

db.c.update({}, [
   {$set:{ newField:{$ifNull: [ "$newField", <newValue> ] } } }
]);

Comment by Georgy Farniev [ 28/Sep/18 ]

+1 for this feature, it could save tons of time when working with complex updates

Comment by Julien Chaumond [ 19/Apr/18 ]

Yes, this should actually be called `$setOnce` (it's what it's called in other document dbs)

Comment by Sergey Churikov [ 08/May/15 ]

+1 for this feature. It cannot be replaced with setOnInsert... I have few places in my project where such update could solve double trip in DB...

Comment by Paulo Pizarro [ 13/Jan/15 ]

$setOnInsert (SERVER-340) does not solve the above problem.

Example:

Consider a collection 'test' with the following document:

{ "_id" : ObjectId("54b54cca3fe00ba1fdab647a"), "a" : 1, "c" : 3 }

After you run the command:

db.test.update(

{ _id: ObjectId("54b54cca3fe00ba1fdab647a") }

, { $set:

{ a: 2 }

, $setOnInsert:

{ b:2 }

},

{ upsert:true }

);

Only the field 'a' was updated because the document already exists the $setOnInsert command is not executed.

We would like to a command to execute only if the FIELD does not exist and not the document.

Comment by Eliot Horowitz (Inactive) [ 04/May/10 ]

See SERVER-340

Generated at Thu Feb 08 02:56:01 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.