Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose and NodeJS: Creating a unique system-generated username

I want to be able to create a system-generated username that is unique. However, the async nature of the mongoose findOne function is tripping me up.

I have a generateUniqueAccountName function that takes in a proposed username and checks with MongoDB if the proposed username is unique. If it is not unique, then a new name is generated until a unique username is found.

Sounds simple enough but generateUniqueAccountName is exited even before a unique name is found. I tried to use Q (my implementation is not shown here) but couldn't make it work either.

Would appreciate any help. Thanks!

This is the generateUniqueAccountName function:

 /**
 * Returns a unique account name based on proposed name
 * @param {String} proposedName
 * @return {Promise}
 */
function generateUniqueAccountName(proposedName) {

  return Account.findOne({accountName: proposedName})
      .then(function(account) {
        if (account != null) {
          console.log('no can do try again: ' + proposedName);
          proposedName += Math.floor((Math.random() * 100) + 1);
          generateUniqueAccountName(proposedName);
        } else {
          console.log('proposed name is unique' + proposedName);
        }
        return proposedName;
      })
      .catch(function(err) {
        console.error(err);
        throw err;
      });
 }

generateUniqueAccountName is called like so:

.then(function(newAccount) {
   // Next generate a unique account name
   console.log('Generating unique account name ...');
   let proposedName = (accounts[i].acctFName + accounts[i].acctLName)
                         .replace(/\s/g, '');

   return generateUniqueAccountName(proposedName.toLowerCase())
            .then(function(accountName) {
               console.log('the unique name is ' + accountName);
               newAccount.accountName = accountName;
               return newAccount;
             })
            .catch(function(err) {
               throw err;
             });
})
.then(saving_part);

This is a sample output:

Generating unique account name ...
no can do try again: teylim
no can do try again: michaelalee
no can do try again: joeykwa
the unique name is teylim86
the unique name is michaelalee72
the unique name is joeykwa91
no can do try again: trishalee
the unique name is trishalee7
proposed name: michaelalee72 is unique
proposed name: joeykwa91 is unique
no can do try again: teylim86
no can do try again: trishalee7
proposed name: teylim8641 is unique
proposed name: trishalee734 is unique
Saving account trishalee7

Looking at trishalee, as you can see, the system tries to save the username trishalee7 even though as the log has shown trishalee7 is not a unique name

like image 989
fab Avatar asked Sep 20 '17 15:09

fab


1 Answers

All what you need to do is to add return statement before generateUniqueAccountName(proposedName):

function generateUniqueAccountName(proposedName) {
  return Account
    .findOne({accountName: proposedName})
    .then(function(account) {
      if (account) {
        console.log('no can do try again: ' + proposedName);
        proposedName += Math.floor((Math.random() * 100) + 1);
        return generateUniqueAccountName(proposedName); // <== return statement here
      }
      console.log('proposed name is unique' + proposedName);
      return proposedName;
    })
    .catch(function(err) {
      console.error(err);
      throw err;
    });
}
like image 125
alexmac Avatar answered Nov 07 '22 12:11

alexmac