-1

I would like to generate a unique ObjectId for a resource to give back clients with the nodejs mongodb driver.

IE:

var ObjectID = require('mongodb').ObjectID;
var objectId = new ObjectID();

Reading about an ObjectId it seems that there are some cases in which this id may not be unique. Even though this is extremely rare I still cannot take a chance on having a duplicate id.

Question #1, Using this driver is it possible (even though unlikely) to get a duplicate id doing this:

var objectId = new ObjectID();

Question #2 (if above is not 100% guarantee to give a unique id):

Does this driver guarantee that for a certain collection the ObjectId that is automatically created when a new document is inserted is unique? If yes, how? If yes, can I somehow duplicate that behavior when calling new ObjectID() myself without a collection?

If the driver or the mongo server ensures (100% of the time) that for a collection every new doc gets a unique id, I could always have a collection of just ids, then when generating a new, empty doc for that collection I would ensure I get a unique ObjectId. However seems like overkill to have another collection just to store ids.

That being said some might ask why not just generate the ObjectId in a collection and update that doc later with data. The answer is that in my case data may not ever come later and I don't want to implement logic to check for empty docs that only contain an id.

lostintranslation
  • 23,756
  • 50
  • 159
  • 262

1 Answers1

0

It's very unlikely that the same ObjectID will generate as mongo guarantees unique ID. objectID is created with a combination of two same values and two different values (unix epoch time, and a random value). However, in any case of a duplicate, you won't be allowed to insert a document as objectID acts as a primary key and insert function will return duplicate key error to your callback. Read more here. The same error is returned if mongo node native library creates a duplicate ObjectID.

UPDATE: again after reading the code base, if "hypothetically" the objectID that was generated by the library isn't unique, the answer is no. We are not ensured by the library that the id is unique, but we are ensured of a duplicate error doesn't matter who or what sent the id.

Here's the process: 1. generates ID 2. Sends straight to server. 3. Returns results.

Mongo isn't looping in nodeJS with existing ids because the library isn't storing it in cache. Read the code base for the library.

Luis Estevez
  • 1,387
  • 12
  • 19
  • Thanks @Luis, but that does not answer my question. In the case of the first link you provided, if you don't provide mongo with an _id on insert mongo will provide you an id. However that document does not talk about the _id that mongo generates ever being a duplicate, even if its rare. So the question still stands, when mongo auto generates an _id does it have extra logic to ensure that _id does not already exist in the collection? – lostintranslation Mar 30 '17 at 23:13
  • In node mongo native library it will return duplicate error. I linked the code base for it. also I answered the question with this "The same error is returned if mongo node native library creates a duplicate ObjectID." – Luis Estevez Mar 30 '17 at 23:21
  • Again, please ignore the driver, what does mongo do not the driver? I can set forceServerObjectId = true in the driver, which means mongo will create the _id. At that point the driver is just a pass through as far as the _id is concerned. Can't find where mongo actually documents that if you do not pass an _id and mongo generates one that it might generate a duplicate within that collection. Which leads me to believe that the mongo server will protect against generating a duplicate _id within a collection. – lostintranslation Mar 31 '17 at 00:25
  • Oh okay, your question wasn't regarding node mongo driver. If forceServerObjectId is true then the driver won't change your document by giving you ObjectId but the Server will guarantee you a unique ObjectID. I understand your question now. – Luis Estevez Mar 31 '17 at 00:43
  • yeah sorry for the confusion. Really meant if the driver OR server can ensure a generated _id for a collection is unique I could solve my problem by having a collection that is solely used for unique _id generation. But only if the driver or server would actually ensure that. From your answer the driver will not ensure this, but I cannot find a definitive answer anywhere in the mongo server docs one way or the other. – lostintranslation Mar 31 '17 at 00:48
  • From the driver's code there's a comment about this "If documents passed in do not contain the **_id** field, one will be added to each of the documents missing it by the driver, mutating the document. This behavior can be overridden by setting the *forceServerObjectId** flag." Also "@param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver." – Luis Estevez Mar 31 '17 at 00:51
  • agreed, but will mongo server ensure _id is not a duplicate? Or could I get a unique constraint violation even if I let the server generate the _id. – lostintranslation Mar 31 '17 at 00:54
  • We can't see the code for the server but this is the closest I can find in the docs. 'mongod will create and populate the _id if the driver or application does not.' I can't find any records online of someone one having a duplicate id from forcing the server. I'm sure the server checks and regenerates if it has to. it would be a bad practice not to. I'm rereading the docs since I'm curious now. – Luis Estevez Mar 31 '17 at 01:12
  • Justing thinking...whats more interesting to me as you pointed out in the driver code, is that the default for the driver is to not let the server create the _id, the driver does. If the server does indeed ensure uniqueness of _ids across a collection, its interesting the default is for the driver is to create its own, potentially non unique _id to pass to the server. Maybe an optimization, as maybe its faster to not let server try to ensure uniqueness??? – lostintranslation Mar 31 '17 at 01:31