2

I have a Mongo collection that has two fields, let's say "name" and "randomString".

I want to create a random string for a name, only if it doesn't exist already. So the first request for { name: "SomeName" } will result in saving e.g. { name: "someName", randomString: "abc" }. The second request will do nothing.

Is there a mongo command for this? All I could find are things like findOneAndUpdate, replaceOne etc, who all support an optional "upsert" but their behavior on match is to update, I want the behavior on match to be do nothing.

I'm not looking for an if-then solution like in this question, as I have a race condition issue - I need to be able to get multiple requests simultaneously without updating the document or failing any of the requests.

Dotan
  • 6,602
  • 10
  • 34
  • 47

3 Answers3

2

Yes there is a command for this you can do this by using $addToSet method. For more info please go through the given link: https://docs.mongodb.com/manual/reference/operator/update/addToSet/

PS: If you still have any confusion regarding this question please feel free to comment further.

Thanks

2

This is the solution I found in the end:

CustomerRandomString.findOneAndUpdate(
    { name: "someName" },
    {
      $setOnInsert: { randomString: generateRandomString() },
    },
    { upsert: true },
  );

The setOnInsert operator only applies when creating a new document, which is exactly what I needed.

EDIT: per the docs, this solution requires a unique index on the field in order to fully avoid duplicates.

Dotan
  • 6,602
  • 10
  • 34
  • 47
0

You can easily do it using the $exists command to check for randomString field and then use $set in an aggregation pipeline to upsert that field.

db.collection.updateMany({"name":someName,"randomString":{$exists: false}},[{$set:{"randomString":"abcd"}}],{upsert:true})

If the condition query doesn't match with any documents, then it returns null.

Note: Aggregation pipeline works in updateMany() only from MongoDB version 4.2 and above.

fractal397
  • 534
  • 1
  • 5
  • 11
  • This doesn't create a new document if it doesn't exist. – Dotan Jul 01 '21 at 13:57
  • Yes, but now it would create a new document over and over because it won't find something that matches `"randomString":{$exists: false}` – Dotan Jul 01 '21 at 14:35
  • What do you mean create over and over? If its does not find any documents it wont do anything apart from creating one new document. And it depends on the search query "name:someName", so once updated all documents with that name , thats it. – fractal397 Jul 01 '21 at 14:41