Firebase – Obtener hijo aleatorio desde el nodo de base de datos

Estoy escribiendo una Firebase Cloud Function que se llama desde una aplicación de Android . La función debe obtener un usuario aleatorio del nodo de usuarios en la Database (cualquier usuario aleatorio pero no el que envió la solicitud) y devolverlo al cliente. El problema es que los datos no están estructurados como una matriz (y no deberían ser ni pueden ser).

Estructura de datos en la base de datos.

Por lo tanto, no puedo elegir un número aleatorio y leer ese nodo, tampoco quiero leer todos los nodos de usuarios e iterarlo porque contiene muchos usuarios y eso consumiría tiempo y recursos. La pregunta:

¿Cómo puedo obtener un usuario aleatorio diferente del que envió la solicitud y cambiar cada vez que se llama a la función (completamente aleatorio), sin consultar una gran cantidad de datos de la base de datos?

El problema principal:

Firebase no realiza un seguimiento del recuento de niños, que necesitamos para la aleatorización. Sin embargo, podemos usar DataSnapshot.numChildren() .

Para evitar esto, puede agregar un elemento de count al nodo /users , que tendría que mantener manualmente, usando las funciones de la nube (por ejemplo, al agregar un usuario, count incrementos y disminución en la eliminación).

Por otro lado, dado que las funciones de la nube están en el servidor, y firebase administrará el caché por usted, no es un gran problema usar DataSnapshot.numChildren() , ya que los datos se almacenarán en caché una vez que se haya ejecutado la función por primera vez, y se actualizará solo cuando haya cambios.

Por lo tanto, recomendaría utilizar la función numChildren() :

 db.ref('/users').once('value').then(snapshot => Math.floor((Math.random() * snapshot.numChildren())) ); 

Alternativamente usando el método de count :

 db.ref('/users/count').once('value').then(snapshot => Math.floor((Math.random() * snapshot.val())) ); 

Obtención del nodo aleatorio:

 db.ref('/users').orderByKey().startAt(random).limitToFirst(1); 

Método 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]); 

Método 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]) 

Puede leer más sobre el orden de consulta y el filtrado en los documentos oficiales:

Recuperando datos – Cómo se ordenan los datos