swdmnd
swdmnd

Reputation: 113

MongoDB updateOne with upsert failed: Duplicate Key

I have a collection with 2 compound unique index, uuid and id. I want to update a document if the collection have a document with unique value of uuid and id (composite unique) and I found in the documentation that updateOne with upsert=true can do this. So, I use:

db.collection("messages").updateOne({uuid:this.uuid, id:new_message.id}, {$set: {uuid: this.uuid, ...new_message}}, {upsert:true})

and this always throw an error saying that there's a document with duplicate value of uuid=xxx and id=yyy. I looked up and found a post stating there's data race happening on update and insert on mongodb upsert operation so this will always happen. Is there another way to do this? How do I properly and efficiently upsert a collection with 1 million documents?

EDIT:

I gave the wrong code for this question. The code should be:

db.collection("messages").updateOne({uuid:this.uuid, key:{id:new_message.key.id}}, {$set: {uuid: this.uuid, ...new_message}}, {upsert:true})

Upvotes: 0

Views: 2741

Answers (2)

swdmnd
swdmnd

Reputation: 113

So, after trying out things I found out that I should use dot notation in the query, I changed it to:

db.collection("messages").updateOne({uuid:this.uuid, "key.id":new_message.key.id}}, {$set: {uuid: this.uuid, ...new_message}}, {upsert:true})

and now it works.

Upvotes: 0

Gibbs
Gibbs

Reputation: 22964

Since you have multi-threading, this is a common problem. All the supported operations in mongo will run into this issue as it is based on your architecture.

You can catch the exception and retry the operation. In this case, one of the threads would be succeeded. Other one will pass through exception handling. This is a feasible workaround.

When do you except both threads updating the same document at the same time? This is a serious design problem. This will alter the desired document state.

Upvotes: 1

Related Questions