[SERVER-8407] upserts handle operators (i.e. $exists) in a manner inconsistent with inserts Created: 30/Jan/13  Updated: 28/Oct/15  Resolved: 29/Sep/14

Status: Closed
Project: Core Server
Component/s: Write Ops
Affects Version/s: 2.2.2, 2.4.11, 2.6.3
Fix Version/s: 2.6.4

Type: Bug Priority: Major - P3
Reporter: Julien Assignee: Ramon Fernandez Marina
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Debian


Issue Links:
Related
related to SERVER-14244 Additional tests for setting fields w... Closed
is related to SERVER-6399 Refactor update() code Closed
Operating System: ALL
Steps To Reproduce:

shape:PRIMARY> db.foo.update({_id: {year: 2012, url: {$exists: false}}}, {$inc: {bar: 1}}, {upsert: true})
 
shape:PRIMARY> db.foo.find()
{ "_id" : { "year" : 2012, "url" : { "$exists" : false } }, "bar" : 1 }

Participants:

 Description   

During an upsert inserting a document, {$exists: false} can be inserted in the collection.



 Comments   
Comment by Ramon Fernandez Marina [ 29/Sep/14 ]

This happens when the document doesn't exist. This behavior has been fixed in 2.6.4:

> db.foo.update({_id: {year: 2012, url: {$exists: false}}}, {$inc: {bar: 1}}, {upsert: true})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 52,
                "errmsg" : "The dollar ($) prefixed field '$exists' in '_id.url.$exists' is not valid for storage."
        }
})

Comment by Julien [ 31/Jan/13 ]

@aaron That's the syntaxe I use now, and it works well.

So I'm ok to let you open a ticket about preventing the insertion of field name containing the $ sign on update and close this one (with a link on the new ticket here for future readers).

Is there any kind of documentation somewhere about the fact that '_id: {url: {$exists: false}}' is inconsistent ?
I think that a link to it in the update page (and some other page) worth it.

Comment by Aaron Staple [ 30/Jan/13 ]

Just to be clear, if the intention is for the query to specify that the _id.url field does not exist then the update would be

update( { '_id.year': 2012, '_id.url': {$exists: false} }, {$inc: {bar: 1}}, {upsert: true} )

and no $exists field is inserted

Comment by Aaron Staple [ 30/Jan/13 ]

Hi Julien - Since your url field is inside _id, it's not treated as a separate query field but a sub field of the _id value the query will try to match.

For inserts we don't allow field names containing $ signs, but for updates we are not consistent about preventing this. I'll make sure we have a ticket open for the update discrepancies.

Generated at Thu Feb 08 03:17:21 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.