Trabajar con listas de datos

Obtener una referencia de base de datos

Para leer o escribir datos de la base de datos, necesita una instancia de DatabaseReference :

DatabaseReference ref = FirebaseDatabase.instance.ref();

Listas de lectura y escritura.

Agregar a una lista de datos

Utilice el método push() para agregar datos a una lista en aplicaciones multiusuario. El método push() genera una clave única cada vez que se agrega un nuevo elemento secundario a la referencia de Firebase especificada. Al utilizar estas claves generadas automáticamente para cada elemento nuevo de la lista, varios clientes pueden agregar elementos secundarios a la misma ubicación al mismo tiempo sin conflictos de escritura. La clave única generada por push() se basa en una marca de tiempo, por lo que los elementos de la lista se ordenan automáticamente cronológicamente.

Puede utilizar la referencia a los nuevos datos devueltos por el método push() para obtener el valor de la clave generada automáticamente por el niño o establecer datos para el niño. La propiedad .key de una referencia push() contiene la clave generada automáticamente.

Puede utilizar estas claves generadas automáticamente para simplificar el aplanamiento de su estructura de datos. Para obtener más información, consulte el ejemplo de distribución de datos .

Por ejemplo, push() podría usarse para agregar una nueva publicación a una lista de publicaciones en una aplicación social:

DatabaseReference postListRef = FirebaseDatabase.instance.ref("posts");
DatabaseReference newPostRef = postListRef.push();
newPostRef.set({
  // ...
});

Escuche eventos infantiles

Los eventos secundarios se activan en respuesta a operaciones específicas que les suceden a los hijos de un nodo a partir de una operación, como un nuevo hijo agregado mediante el método push() o un hijo que se actualiza mediante el método update() .

Evento Uso típico
onChildAdded Recupera listas de elementos o escucha adiciones a una lista de elementos. Este evento se activa una vez para cada hijo existente y luego nuevamente cada vez que se agrega un hijo nuevo a la ruta especificada. Al oyente se le pasa una instantánea que contiene los datos del nuevo niño.
onChildChanged Escuche los cambios en los elementos de una lista. Este evento se activa cada vez que se modifica un nodo secundario. Esto incluye cualquier modificación a los descendientes del nodo hijo. La instantánea pasada al detector de eventos contiene los datos actualizados del niño.
onChildRemoved Escuche los elementos que se eliminan de una lista. Este evento se activa cuando se elimina un hijo inmediato. La instantánea pasada al bloque de devolución de llamada contiene los datos del hijo eliminado.
onChildMoved Escuche los cambios en el orden de los elementos en una lista ordenada. Los eventos onChildMoved siempre siguen al evento onChildChanged que provocó que cambiara el orden del artículo (según su método de ordenamiento actual).

Cada uno de estos juntos puede ser útil para escuchar cambios en un nodo específico en una base de datos. Por ejemplo, una aplicación de blogs sociales podría utilizar estos métodos juntos para monitorear la actividad en los comentarios de una publicación, como se muestra a continuación:

final commentsRef = FirebaseDatabase.instance.ref("post-comments/$postId");
commentsRef.onChildAdded.listen((event) {
  // A new comment has been added, so add it to the displayed list.
});
commentsRef.onChildChanged.listen((event) {
  // A comment has changed; use the key to determine if we are displaying this
  // comment and if so displayed the changed comment.
});
commentsRef.onChildRemoved.listen((event) {
  // A comment has been removed; use the key to determine if we are displaying
  // this comment and if so remove it.
});

Escuche eventos de valor

Si bien escuchar eventos secundarios es la forma recomendada de leer listas de datos, hay situaciones en las que es útil escuchar eventos de valor en una referencia de lista.

Adjuntar un detector value a una lista de datos devolverá la lista completa de datos como una única instantánea que luego podrá recorrer para acceder a niños individuales.

Incluso cuando solo hay una coincidencia para la consulta, la instantánea sigue siendo una lista; solo contiene un solo elemento. Para acceder al elemento, debe recorrer el resultado:

myTopPostsQuery.onValue.listen((event) {
  for (final child in event.snapshot.children) {
    // Handle the post.
  }
}, onError: (error) {
  // Error.
});

Este patrón puede resultar útil cuando desea recuperar todos los elementos secundarios de una lista en una sola operación, en lugar de escuchar eventos secundarios adicionales agregados.

Ordenar y filtrar datos

Puede utilizar la clase Query para recuperar datos ordenados por clave, por valor o por valor de un hijo. También puede filtrar el resultado ordenado según un número específico de resultados o un rango de claves o valores.

ordenar datos

Para recuperar datos ordenados, comience especificando uno de los métodos de ordenación para determinar cómo se ordenan los resultados:

Método Uso
orderByChild() Ordene los resultados por el valor de una clave secundaria especificada o una ruta secundaria anidada.
orderByKey() Ordene los resultados por claves secundarias.
orderByValue() Ordene los resultados por valores secundarios.

Sólo puedes utilizar un método de orden por vez. Llamar a un método de orden por varias veces en la misma consulta genera un error.

El siguiente ejemplo demuestra cómo puedes recuperar una lista de las publicaciones principales de un usuario ordenadas por su número de estrellas:

final myUserId = FirebaseAuth.instance.currentUser?.uid;
final topUserPostsRef = FirebaseDatabase.instance
    .ref("user-posts/$myUserId")
    .orderByChild("starCount");

Esto define una consulta que, cuando se combina con un escucha secundario , sincroniza al cliente con las publicaciones del usuario desde la ruta en la base de datos en función de su ID de usuario, ordenadas por la cantidad de estrellas que ha recibido cada publicación. Esta técnica de utilizar ID como claves de índice se denomina distribución en abanico de datos; puede leer más sobre esto en Estructurar su base de datos .

La llamada al método orderByChild() especifica la clave secundaria para ordenar los resultados. En este caso, las publicaciones se ordenan por el valor de su respectivo hijo "starCount" . Las consultas también se pueden ordenar por elementos secundarios anidados, en caso de que tenga datos similares a estos:

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

En este caso, podemos ordenar los elementos de nuestra lista por valores anidados bajo la clave metrics especificando la ruta relativa al hijo anidado en nuestra llamada orderByChild() .

final mostViewedPosts =
    FirebaseDatabase.instance.ref('posts').orderByChild('metrics/views');

Para obtener más información sobre cómo se ordenan otros tipos de datos, consulte Cómo se ordenan los datos de la consulta .

Filtrar datos

Para filtrar datos, puede combinar cualquiera de los métodos de límite o rango con un método de ordenar por al crear una consulta.

Método Uso
limitToFirst() Establece el número máximo de elementos que se devolverán desde el principio de la lista ordenada de resultados.
limitToLast() Establece el número máximo de elementos que se devolverán desde el final de la lista ordenada de resultados.
startAt() Devuelve elementos mayores o iguales a la clave o valor especificado, según el método de ordenamiento elegido.
startAfter() Devuelve elementos mayores que la clave o el valor especificado según el método de ordenamiento elegido.
endAt() Devuelve elementos menores o iguales a la clave o valor especificado, según el método de ordenamiento elegido.
endBefore() Devuelve artículos con menos de la clave o valor especificado según el método de ordenación elegido.
equalTo() Devuelve elementos iguales a la clave o valor especificado, según el método de ordenamiento elegido.

A diferencia de los métodos de orden por, puede combinar múltiples funciones de límite o rango. Por ejemplo, puede combinar los métodos startAt() y endAt() para limitar los resultados a un rango específico de valores.

Limitar el número de resultados.

Puede utilizar los métodos limitToFirst() y limitToLast() para establecer un número máximo de elementos secundarios que se sincronizarán para un evento determinado. Por ejemplo, si usa limitToFirst() para establecer un límite de 100, inicialmente solo recibirá hasta 100 eventos onChildAdded . Si tiene menos de 100 elementos almacenados en su base de datos de Firebase, se activa un evento onChildAdded para cada elemento.

A medida que los elementos cambian, recibe eventos onChildAdded para los elementos que ingresan a la consulta y eventos onChildRemoved para los elementos que salen de ella, de modo que el número total permanezca en 100.

El siguiente ejemplo demuestra cómo una aplicación de blogs de ejemplo define una consulta para recuperar una lista de las 100 publicaciones más recientes de todos los usuarios:

final recentPostsRef = FirebaseDatabase.instance.ref('posts').limitToLast(100);

Este ejemplo solo define una consulta; para sincronizar realmente los datos, necesita tener un oyente adjunto.

Filtrar por clave o valor

Puede utilizar startAt() , startAfter() , endAt() , endBefore() y equalTo() para elegir puntos de inicio, finalización y equivalencia arbitrarios para las consultas. Esto puede resultar útil para paginar datos o buscar elementos con elementos secundarios que tengan un valor específico.

Cómo se ordenan los datos de la consulta

Esta sección explica cómo se ordenan los datos mediante cada uno de los métodos de ordenación en la clase Query .

orderByChild

Cuando se utiliza orderByChild() , los datos que contienen la clave secundaria especificada se ordenan de la siguiente manera:

  1. Los niños con un valor null para la clave secundaria especificada son lo primero.
  2. Los niños con un valor false para la clave secundaria especificada son los siguientes. Si varios hijos tienen un valor false , se ordenan lexicográficamente por clave.
  3. Los niños con un valor true para la clave secundaria especificada son los siguientes. Si varios hijos tienen un valor true , se ordenan lexicográficamente por clave.
  4. Los niños con un valor numérico vienen a continuación, ordenados en orden ascendente. Si varios hijos tienen el mismo valor numérico para el nodo hijo especificado, se ordenan por clave.
  5. Las cadenas van después de los números y están ordenadas lexicográficamente en orden ascendente. Si varios hijos tienen el mismo valor para el nodo hijo especificado, se ordenan lexicográficamente por clave.
  6. Los objetos van al final y se ordenan lexicográficamente por clave en orden ascendente.

orderByKey

Cuando usas orderByKey() para ordenar tus datos, los datos se devuelven en orden ascendente por clave.

  1. Los niños con una clave que se puede analizar como un entero de 32 bits aparecen primero, ordenados en orden ascendente.
  2. Los niños con un valor de cadena como clave vienen a continuación, ordenados lexicográficamente en orden ascendente.

orderByValue

Cuando se usa orderByValue() , los niños se ordenan por su valor. Los criterios de orden son los mismos que en orderByChild() , excepto que se usa el valor del nodo en lugar del valor de una clave secundaria especificada.

Separar oyentes

Las devoluciones de llamada se eliminan llamando al método off() en la referencia de tu base de datos de Firebase.

Puede eliminar un único oyente pasándolo como parámetro a off() . Al off() en la ubicación sin argumentos se eliminan todos los oyentes en esa ubicación.

off() en un oyente principal no elimina automáticamente los oyentes registrados en sus nodos secundarios; También se debe invocar off() en cualquier oyente secundario para eliminar la devolución de llamada.

Próximos pasos