0

I have a collection called users. I want to add a user to that collection but it should fail if a user with the same name already exists. If creation succeeds I would like to initialize it with some data, e.g. password hash.

I cannot use an update upsert like follows:

name = ...
password_hash = ...
db.users.update({ "name": name }, { "name": name, "hash": password_hash }, upsert=True)

because that would overwrite the password hash of an existing user. Essentially I want to atomically do the following:

name = ...
password_hash = ...
if db.users.find_one({ "name": name }) is None: # Line A
    db.users.insert_one({ "name": name, "hash": password_hash }) # Line B

However I cannot use that exact code because a user with name could be added between Line A and Line B meaning I would have two users with the same name.

I also cannot use an empty upsert and then add the data afterwards in the case that it created a new user, because that data may be queried between the user being created and the data being added. I.e. it is not atomic.

I have tried reading other SO questions and answers (they all suggest the empty upsert method which doesn't work), have tried reading the documentation and have tried general googling without being able to find anything. I am using Python so if you can write an answer in Python that would be good but don't avoid answering if you have to write it in a different language.

Llew Vallis
  • 337
  • 4
  • 12

1 Answers1

1

You can create an index and specify that name is a unique field. take a look here:

https://docs.mongodb.com/manual/core/index-unique/

that should solve you problem.

Any update / insert operation that don't comply with the index will fail.

Mazki516
  • 997
  • 1
  • 10
  • 20