Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Randomly generating a value not in mongodb?

I'm trying to generate session ids in Node and store them in MongoDB. For my application I only want to generate a random 6 digit number (this number is used to sync two sessions so it's short for users to easily copy). I want to generate a number that is not already in my sessions collection in MongoDB. My first thought which will probably work 99% of the time is this:

function GetSessionKey(cb) {
    var key = parseInt(Math.random() * 1000000).toString();
    while (key.length < 6) key = '0' + key;
    db.sessions.find({ Key: key }, function (err, docs) {
        if (!err && docs.length == 0) {
            cb(key);
        } else {
            GetSessionKey(cb);
        }
    });
}

But there is a slim chance that the generated key constantly picks existing keys in mongo. Or the possibility that all keys are already in use (which I do not expect to happen).

I know Node is asynchronous but does that mean that a recursive async call like this will fill up the stack if it keeps getting called? Or do async calls not get put on the stack? Is there a better way to generate short unique keys? Old keys will be removed and can be reused so I don't think it's be a ticking time bomb. I'm just worried that the random aspect may cause trouble.

like image 426
Corey Ogburn Avatar asked Oct 18 '25 04:10

Corey Ogburn


1 Answers

An alternative is to use MongoDB to enforce uniqueness. For example, create an unique index on the Key field in the Mongo shell:

db.sessions.ensureIndex( { Key: 1 }, { unique: true } )

Modify the Node.js code to insert the generated random value and test the err variable for duplicate key errors. If there is no error, you're good to go. Otherwise, regenerate the value and try again. You can test for duplicate key errors like this:

...
db.sessions.insert({ Key: key }, function (err, docs) {
  ...
  if (err) {
    if (err.code && err.code == 11000) {
      // Duplicate key error. Generate a new random value and insert again.
    } else {
      throw err;
    }
  }
  ...

If you can store the generated key in the _id field instead of Key, then you can skip ensureIndex(...) as MongoDB automatically creates an unique index on _id.

like image 137
jamestyj Avatar answered Oct 20 '25 19:10

jamestyj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!