Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase - Get Random Child From Database Node

I'm writing a Firebase Cloud Function that is called from an Android app. The function should get a random user from the users node in the Database (Any random user but not the one who sent the request) and return it to the client. The problem is that the data is not structured as an array (And it should not be and can't be).

Data structure in the database.

So I can't pick a random number and read that node, I also don't want to read all the users node and iterate it because it contains a lot of users and that would be time and resources-consuming. The Question:

How can I get a random user different from the one who sent the request, and changes with every time the function is called (completely random), while not querying a lot of data from the database?

like image 789
Ameer Taweel Avatar asked Oct 28 '25 07:10

Ameer Taweel


1 Answers

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

like image 109
FatalMerlin Avatar answered Oct 30 '25 23:10

FatalMerlin



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!