So I am working on a storing users information in my database and in addition to the standard data I get from a Firebase User, I wanted to add my own custom data. I am setting up a profile page for each of my users and I wanted to generate a random 10 digit number to be their profileID. I then store it in my database just in case I need it. However, I need them to be unique numbers and for them not to repeat so I'm trying to query the database to check if the profileID that I generated is already in use and if so, generate another one. However, I can't figure out how to repeat a query in Firestore other than maybe using a loop but that doesn't seem like it would work.
const usersRef: AngularFirestoreCollection = this.afs.collection('users');
var query = usersRef.ref.where("profileID", '==', profileID);
query.get().then((querySnapshot) => {
if (!querySnapshot.empty) {
profileID = this.getRandomProfileID();
}
})
A recursive function like this seems the way to go:
function getRandomProfileID() {
return new Promise(function(resolve, reject) {
var profileID = ....
var query = usersRef.ref.where("profileID", '==', profileID);
query.get().then((querySnapshot) => {
if (!querySnapshot.empty) {
this.getRandomProfileID();
}
else {
resolve(profileID);
}
})
})
}
And then you'd call it with:
getRandomProfileID().then(function(profileID) {
console.log(profileID);
});
Or if you're using a more modern version of JavaScript:
var profileID = await getRandomProfileID();
console.log(profileID);
As Doug pointed out, with async
/await
you can even do without the recursive function entirely:
while (true) {
let profileID = ....
let snapshot = await usersRef.ref.where("profileID", '==', profileID).get()
if (!snapshot.empty) {
break;
}
}
console.log("Found unique ID: " + profileID);
But there are some things still to consider with this approach:
Another user may generate the same profile ID between the time you generate and check it, and actually creating it. If this is a concern, you should probably use a transaction for the function above, and have it create the profile document. If it's not a realistic concern, you should still ensure in security rules that no user can ever overwrite a document that was already created by another user.
If you're going to use your own profile ID in a lot of places to identify the user, consider creating an additional collection where each document name/ID is the profile ID, and the document contents are the key into the users collection. If you're going to uniquely identify the users by their profile ID, consider using the profile ID as the key of their document in the users collection, instead of whatever key you know use.