[SERVER-65423] Cannot create field in element. Created: 11/Apr/22  Updated: 27/Oct/23  Resolved: 14/Apr/22

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

Type: Bug Priority: Major - P3
Reporter: Roman Kazanovskyi Assignee: Chris Kelly
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Participants:

 Description   

Test scenario:

db.foo.insertOne({
    "name" : "name",
    "attr": null
})
 
db.foo.updateOne(
    {name : "name"},
    {$set : {"attr.key": "key"}}
    )
//com.mongodb.MongoWriteException: Write operation error on server localhost:27017.
// Write error: WriteError{code=28, message='Cannot create field 'key' in element {attr: null}', details={}}.
 
 
db.version() // 5.0.2

But documentation for $set says:

If the field does not exist, $set will add a new field with the specified value, provided that the new field does not violate a type constraint. If you specify a dotted path for a non-existent field, $set will create the embedded documents as needed to fulfill the dotted path to the field.



 Comments   
Comment by Chris Kelly [ 14/Apr/22 ]

Hello roman.kazanovskyi@aifora.com,

I was able to reproduce this behavior on MongoDB 5.0.2. While the documentation is correct in that MongoDB will automatically create the subdocument for you if it doesn't exist using $set with dotted notation, it will only do so for non-existent fields. Even though your field "attr" has a value of null, the field itself exists at this point.
In your case, you can get around this by any of the following:

If you want to use dotted notation:

  • not creating the "attr" field to begin with in your initial insert
  • specifying the nested document fields you want to update ahead of time i.e: 

    "attr" :{ "key": "key value here" }

If you want to write the whole document you wish to set instead:

  • inserting document instead of dotted string

     
        {$set : {
            "attr":
                    {
                            "key" : "test"
                    }
            }
        }
    
    

I can see how the statement you shared from the documentation may be strange to parse however; it appears to imply that $set will add new child fields on dotted paths since the child doesn't exist yet ("attr.key" in your example), even though the parent does exist ("attr" in this case).

For now, feel free to try any of the options I listed above, or refer to our community for further help by posting on the MongoDB Developer Community Forums.

Thank you for the report!

Regards,
Christopher

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