Cómo recuperar datos

En este documento, se tratan los aspectos básicos de la recuperación de datos y cómo ordenar y filtrar datos en Firebase.

Antes de comenzar

Antes de poder usar Realtime Database, tendrás que hacer lo siguiente:

  • Registra tu proyecto de Unity y configúralo para usar Firebase.

    • Si tu proyecto de Unity ya usa Firebase, significa que ya está registrado y configurado para Firebase.

    • Si aún no tienes un proyecto de Unity, puedes descargar una app de ejemplo.

  • Agrega el SDK de Firebase Unity (específicamente, FirebaseDatabase.unitypackage) a tu proyecto de Unity.

Ten en cuenta que agregar Firebase a tu proyecto de Unity implica realizar tareas en Firebase console y en tu proyecto abierto de Unity (por ejemplo, descargar archivos de configuración de Firebase desde la consola y moverlos a tu proyecto de Unity).

Recupera datos

Para recuperar datos en Firebase, debes invocar GetValueAsync() o adjuntar un evento en una referencia de FirebaseDatabase. El objeto de escucha de eventos se llama una vez para el estado inicial de los datos y cada vez que los datos cambian.

Obtén una DatabaseReference

A fin de leer de la base de datos, necesitas una instancia de DatabaseReference:

using Firebase;
using Firebase.Database;
using Firebase.Extensions.TaskExtension; // for ContinueWithOnMainThread

public class MyScript: MonoBehaviour {
  void Start() {
    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

Lee los datos una sola vez

Puedes usar el método GetValueAsync para leer una instantánea estática del contenido de una ruta específica una vez. El resultado de la tarea contendrá una instantánea con todos los datos de esa ubicación, incluidos los de nivel secundario. Si no hay datos, la instantánea tiene el valor null.

    FirebaseDatabase.DefaultInstance
      .GetReference("Leaders")
      .GetValueAsync().ContinueWithOnMainThread(task => {
        if (task.IsFaulted) {
          // Handle the error...
        }
        else if (task.IsCompleted) {
          DataSnapshot snapshot = task.Result;
          // Do something with snapshot...
        }
      });

Detecta eventos

Puedes agregar agentes de escucha de eventos para suscribirte a cambios en los datos.

Evento Uso común
ValueChanged Lee y detecta cambios en el contenido de una ruta.
ChildAdded Recupera listas de elementos o detecta elementos agregados a una lista. Se sugiere su uso con ChildChanged y ChildRemoved para supervisar los cambios en las listas.
ChildChanged Detecta cambios en los elementos de una lista. Úsalo con ChildAdded y ChildRemoved para supervisar los cambios en las listas.
ChildRemoved Detecta cuando se quitan elementos de una lista. Úsalo con ChildAdded y ChildChanged para supervisar los cambios en las listas.
ChildMoved Detecta cambios en el orden de los elementos de una lista ordenada. Los eventos ChildMoved siempre siguen al evento ChildChanged que generó el cambio en el orden de los elementos (en función del método de ordenamiento actual).

Evento ValueChanged

Puedes usar el evento ValueChanged para suscribirte a los cambios del contenido de una ruta determinada. Este evento se activa cuando se adjunta el objeto de escucha y vuelve a activarse cada vez que cambian los datos (incluidos los de segundo nivel). La devolución de llamada del evento recibe una instantánea que contiene todos los datos de esa ubicación, incluidos los datos de nivel secundario. Si no hay datos, la instantánea tiene el valor null.

El siguiente ejemplo demuestra un juego que recupera las puntuaciones de una tabla de clasificación en la base de datos:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

ValueChangedEventArgs contiene una DataSnapshot con los datos que se encontraban en la ubicación especificada de la base de datos en el momento del evento. Si llamas a Value sobre una instantánea, se muestra un Dictionary<string, object> que representa los datos. Si no existen datos en la ubicación, la llamada a Value muestra null.

En este ejemplo, también se examina args.DatabaseError para ver si se cancela la operación de lectura. Por ejemplo, una lectura puede cancelarse si el cliente no tiene permiso para leer datos de una ubicación en la base de datos de Firebase. El DatabaseError indicará por qué se produjo el error.

Más tarde puedes anular la suscripción al evento con cualquier DatabaseReference que tenga la misma ruta de acceso. Las instancias de DatabaseReference son efímeras y pueden considerarse como una forma de acceder a cualquier ruta y consulta.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged -= HandleValueChanged; // unsubscribe from ValueChanged.
    }

Eventos secundarios

Los eventos secundarios se activan en respuesta a operaciones específicas que se ejecutan en los elementos secundarios de un nodo a partir de una operación, como un elemento secundario nuevo que se agrega a través del método Push() o un elemento secundario que se actualiza a través del método UpdateChildrenAsync(). Cada uno de estos, en combinación, puede ser útil para detectar cambios en un nodo específico de una base de datos. Por ejemplo, un juego podría usar estos métodos en combinación para supervisar la actividad en los comentarios de una sesión del juego, como se muestra a continuación:

      var ref = FirebaseDatabase.DefaultInstance
      .GetReference("GameSessionComments");

      ref.ChildAdded += HandleChildAdded;
      ref.ChildChanged += HandleChildChanged;
      ref.ChildRemoved += HandleChildRemoved;
      ref.ChildMoved += HandleChildMoved;
    }

    void HandleChildAdded(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildChanged(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildRemoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildMoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

El evento ChildAdded se usa normalmente para recuperar una lista de elementos en una base de datos de Firebase. El evento ChildAdded se genera una vez por cada elemento secundario existente y otra vez cada vez que se agrega un nuevo elemento secundario a la ruta especificada. El objeto de escucha recibe una instantánea que contiene los datos del nuevo elemento secundario.

El evento ChildChanged se genera cada vez que se modifica un nodo secundario. Esto incluye cualquier modificación en descendientes del nodo secundario. Por lo general, se usa en combinación con los eventos ChildAdded y ChildRemoved para responder a cambios en una lista de elementos. La instantánea que se pasa al objeto de escucha de eventos contiene los datos actualizados del elemento secundario.

El evento ChildRemoved se activa cuando se quita un campo secundario inmediato. Por lo general, se usa en combinación con ChildAdded y ChildChanged. El resumen que se pasa a la devolución de llamada de eventos contiene los datos del elemento secundario eliminado.

El evento ChildMoved se activa siempre que se genera un evento ChildChanged debido a una actualización que hace que se cambie el orden de ese elemento secundario. Se usa con datos que se ordenan con OrderByChild o OrderByValue.

Cómo ordenar y filtrar datos

Puedes usar la clase Query de Realtime Database para recuperar los datos organizados por clave, por valor o por valor del elemento secundario. También puedes filtrar el resultado ordenado de acuerdo con una cantidad específica de resultados o un rango de claves o valores.

Ordena los datos

Para recuperar datos ordenados, comienza por especificar uno de los métodos de ordenamiento, a fin de determinar cómo se presentarán los resultados:

Método Uso
OrderByChild() Ordena los resultados según el valor de una clave secundaria especificada.
OrderByKey() Ordena los resultados según las claves secundarias.
OrderByValue() Ordena los resultados según los valores secundarios.

Puedes usar solo un método de ordenamiento a la vez. Si invocas un método de ordenamiento varias veces en la misma consulta, se genera un error.

El siguiente ejemplo demuestra cómo podrías crear una suscripción a una tabla de clasificación de puntajes ordenada por puntaje.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

Esto define una consulta que, cuando se combina con un el objeto de escucha de eventos valuechanged, sincroniza el cliente con la tabla de clasificación de la base de datos, ordenada según la puntuación de cada entrada. Para obtener más información sobre cómo estructurar tus datos en forma eficiente, consulta Estructura tu base de datos.

La llamada al método OrderByChild() especifica la clave secundaria según la que se deben ordenar los resultados. En este caso, los resultados se ordenan según el valor de "score" en cada elemento secundario. Para obtener más información sobre cómo se ordenan otros tipos de datos, consulta la sección Cómo se ordenan los datos de las consultas.

Cómo filtrar datos

Para filtrar datos, puedes combinar cualquiera de los métodos de límite o rango con un método de ordenamiento cuando generes una consulta.

Método Uso
LimitToFirst() Configura la cantidad máxima de elementos que pueden mostrarse desde el comienzo de la lista de resultados ordenada.
LimitToLast() Define la cantidad máxima de elementos que pueden mostrarse desde el final de la lista de resultados ordenada.
StartAt() Muestra elementos con un valor igual o superior a la clave o el valor que se especifica según el método de ordenamiento seleccionado.
EndAt() Muestra elementos con un valor inferior o igual a la clave o el valor que se especifica según el método de ordenamiento seleccionado.
EqualTo() Muestra elementos con un valor igual a la clave o el valor que se especifica según el método de ordenamiento seleccionado.

A diferencia de los métodos de ordenamiento, se puede combinar varias funciones de límite y rango. Por ejemplo, puedes combinar los métodos StartAt() y EndAt() para limitar los resultados a un rango de valores específico.

Incluso cuando hay una sola coincidencia para la consulta, la instantánea es una lista, aunque contenga un solo elemento.

Limita la cantidad de resultados

Puedes usar los métodos LimitToFirst() y LimitToLast() a fin de establecer una cantidad máxima de elementos secundarios que se sincronicen para una devolución de llamada determinada. Por ejemplo, si usas LimitToFirst() para establecer un límite de 100, inicialmente solo recibes hasta 100 devoluciones de llamada de tipo ChildAdded. Si hay menos de 100 elementos almacenados en la base de datos de Firebase, se activa una devolución de llamada ChildAdded por cada elemento.

A medida que los elementos cambien, recibirás devoluciones de llamadas de tipo ChildAdded por los elementos que ingresen en la consulta y devoluciones de llamadas de tipo ChildRemoved por los elementos que queden fuera para que la cantidad total continúe siendo 100.

Por ejemplo, el siguiente fragmento de código muestra la primera puntuación de la tabla de clasificación:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score").LimitToLast(1)
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

Filtra por clave o valor

Puedes usar StartAt(), EndAt() y EqualTo() a fin de elegir puntos de inicio, finalización y equivalencia arbitrarios para las consultas. Esto puede ser útil para paginar datos o encontrar elementos con campos secundarios que tengan un valor específico.

Cómo se ordenan los datos de las consultas

En esta sección, se explica cómo se ordenan los datos en cada uno de los métodos de ordenamiento de la clase Query.

OrderByChild

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

  1. Los elementos secundarios cuyas claves secundarias especificadas posean el valor null irán en primer lugar.
  2. A continuación, aparecerán los elementos secundarios que tengan el valor false en la clave secundaria especificada. Si hay varios elementos secundarios con el valor false, se ordenan lexicográficamente por clave.
  3. A continuación, aparecerán los elementos secundarios que tengan el valor true en la clave secundaria especificada. Si hay varios elementos secundarios con el valor true, se ordenan lexicográficamente por clave.
  4. Luego vienen los elementos secundarios con valor numérico, que se ordenan en sentido ascendente. Si varios elementos secundarios tienen el mismo valor numérico en el nodo secundario especificado, se ordenan según la clave.
  5. Las strings van después de los números y se ordenan de manera lexicográfica, en sentido ascendente. Si varios elementos secundarios tienen el mismo valor en el nodo secundario especificado, se ordenan de manera lexicográfica según la clave.
  6. Los objetos quedan en último lugar y se ordenan de manera lexicográfica según su clave, en orden ascendente.

OrderByKey

Cuando ordenas los datos con OrderByKey(), estos se muestran en orden ascendente, según la clave.

  1. Los elementos secundarios con una clave que puede analizarse como un número entero de 32 bits van primero, ordenados en sentido ascendente.
  2. Los elementos secundarios con un valor de string como clave van después y ordenados de manera lexicográfica, en sentido ascendente.

OrderByValue

Cuando usas OrderByValue(), los elementos secundarios se ordenan según el valor. Se utiliza el mismo criterio de orden que para OrderByChild(), excepto que se usa el valor del nodo en lugar del valor de una clave secundaria especificada.