19

In this post, the accepted answer explains that you cannot have the same fields under $set and $setOnInsert in an upsert operation.

Can someone explain why this is? It seems like the $setOnInsert shouldn't conflict with $set, since the former is used when a document is inserted, and the latter is used when the document is updated.

Community
  • 1
  • 1
jtmarmon
  • 5,727
  • 7
  • 28
  • 45
  • 8
    Honestly, I don't have an explanation for why this is the case now; I'd like to see this implemented as well. There is an enhancement request, [SERVER-10711](https://jira.mongodb.org/browse/SERVER-10711), to allow `$set` and `$setOnInsert` to work in the same update on the same field. You can comment, watch, and upvote that issue to raise its priority. – wdberkeley Dec 18 '14 at 18:19
  • 4
    thank you for pointing this out @wdberkeley. do you know if there's a workaround to this without needing two queries? – jtmarmon Dec 18 '14 at 19:00

2 Answers2

5

I faced this problem. If someone is looking for a solution, you need to understand how the $set and $setOnInsert mechanism works $set refreshes if found (ignoring $setOnInsert) $setOnInsert inserts a new record (and then executes $set) I did not know this and thought that only one operator would work. This way I was able to get rid of duplicate fields

  • Hmmm! That's why they don't allow the same field in both at the same time. That makes sense (for the way it works). Although I still think they should support something to allow setting a different value on insert, as [the comment below](https://stackoverflow.com/questions/27552352/mongodb-duplicate-fields-in-set-and-setoninsert/33844252?noredirect=1#comment74261104_33844252) – maganap Feb 25 '22 at 09:15
1

$set operator is used on upsert too. So it's nonsense to refer same fields both on $set and $setOnInsert.

Just try this on an empty collection:

db.items.remove();
db.items.update({},{$set:{a:1},$setOnInsert:{b:2}},{upsert:1})
db.items.find({});
hemme
  • 1,654
  • 1
  • 15
  • 22
  • 38
    It's not "nonsense". For example, I need a field to be `true` if the document was just inserted, and to be `false` if it was just updated. If same field exists in both `$set`(as `false`) and `$setOnInsert`(as `true`), and the document is inserted, the field in `$setOnInsert` should take precedence even though it exists as well in the `$set` section. – maganap Apr 25 '17 at 08:56
  • 1
    @maganap i wanna do exactly that. is there a way ? – Gray Hat Feb 24 '22 at 08:56
  • @GrayHat It's been a long time since I last worked with MongoDB, so I really couldn't tell. Sorry I can't help here. – maganap Feb 25 '22 at 09:11