The main problem:
Firebase doesn't keep track of the child count, which we need for the randomization. We can however use DataSnapshot.numChildren()
.
To avoid this, you can add a count
element to the /users
node, which you would have to maintain manually, using cloud functions (e.g. when adding a user, increment count
, and decrement on deletion).
On the other hand, since the cloud functions are on the server, and firebase will manage the cache for you, it is not a big deal to actually use DataSnapshot.numChildren()
, since the data will be cached once the function has been executed for the first time, and will be updated only when there are changes.
Therefore I would recommend to utilize the numChildren()
function:
db.ref('/users').once('value').then(snapshot =>
Math.floor((Math.random() * snapshot.numChildren()))
);
Alternatively using the count
-method:
db.ref('/users/count').once('value').then(snapshot =>
Math.floor((Math.random() * snapshot.val()))
);
Getting the random Node:
db.ref('/users').orderByKey().startAt(random).limitToFirst(1);
Method 1:
// https://stackoverflow.com/a/38423694/4161937
// attach permanent listener to force firebase caching (not sure if it works for this case)
db.ref('/users').on('value', () => {});
// will read #random amount of items
db.ref('/users').orderByKey().limitToFirst(random).once('value').then(users => Object.keys(users)[random]);
Method 2:
// https://stackoverflow.com/a/38423694/4161937
// attach permanent listener to force firebase caching
db.ref('/users').on('value', () => {});
db.ref('/users').once('value').then(users => Object.keys()[random])
You can read more about query order- and filtering in the official docs:
Retrieving Data - How Data is Ordered