Recuperar datos con Firebase Realtime Database para C++

Este documento cubre los conceptos básicos de la recuperación de datos y cómo ordenar y filtrar datos de Firebase.

Antes de que empieces

Asegúrese de haber configurado su aplicación y de poder acceder a la base de datos como se describe en la guía Get Started .

Recuperando datos

Los datos de Firebase se recuperan mediante una llamada única a GetValue() o adjuntándolos a un ValueListener en una referencia FirebaseDatabase . El detector de valores se llama una vez para el estado inicial de los datos y nuevamente cada vez que cambian los datos.

Obtener una referencia de base de datos

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

    // Get the root reference location of the database.
    firebase::database::DatabaseReference dbref = database->GetReference();

Leer datos una vez

Puede utilizar el método GetValue() para leer una vez una instantánea estática del contenido en una ruta determinada. El resultado de la tarea contendrá una instantánea que contendrá todos los datos en esa ubicación, incluidos los datos del niño. Si no hay datos, la instantánea devuelta es null .

  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("Leaders").GetValue();

En ese momento se realizó la solicitud, pero tenemos que esperar a que se complete el futuro antes de poder leer el valor. Dado que los juegos generalmente se ejecutan en un bucle y se basan menos en la devolución de llamadas que otras aplicaciones, normalmente realizarás una encuesta para completarlos.

  // In the game loop that polls for the result...

  if (result.status() != firebase::kFutureStatusPending) {
    if (result.status() != firebase::kFutureStatusComplete) {
      LogMessage("ERROR: GetValue() returned an invalid result.");
      // Handle the error...
    } else if (result.error() != firebase::database::kErrorNone) {
      LogMessage("ERROR: GetValue() returned error %d: %s", result.error(),
                 result.error_message());
      // Handle the error...
    } else {
      firebase::database::DataSnapshot snapshot = result.result();
      // Do something with the snapshot...
    }
  }

Esto muestra algunas comprobaciones de errores básicas; consulte la referencia de firebase::Future para obtener más información sobre la verificación de errores y formas de determinar cuándo el resultado está listo.

Escuche eventos

Puede agregar oyentes para que se suscriban ante cambios en los datos:

Clase base ValueListener

Llamar de vuelta Uso típico
OnValueChanged Lea y escuche los cambios en todo el contenido de una ruta.

Clase base OnChildListener

OnChildAdded Recupera listas de elementos o escucha adiciones a una lista de elementos. Uso sugerido con OnChildChanged y OnChildRemoved para monitorear cambios en las listas.
OnChildChanged Escuche los cambios en los elementos de una lista. Úselo con OnChildAdded y OnChildRemoved para monitorear los cambios en las listas.
OnChildRemoved Escuche los elementos que se eliminan de una lista. Úselo con OnChildAdded y OnChildChanged para monitorear los cambios en las listas.
OnChildMoved Escuche los cambios en el orden de los elementos en una lista ordenada. Las devoluciones de llamada OnChildMoved siempre siguen a las devoluciones de llamada OnChildChanged debido al cambio de orden del artículo (según su método de ordenamiento actual).

Clase ValueListener

Puede utilizar las devoluciones de llamada OnValueChanged para suscribirse a cambios en el contenido en una ruta determinada. Esta devolución de llamada se activa una vez cuando se adjunta el oyente y nuevamente cada vez que cambian los datos, incluidos los secundarios. A la devolución de llamada se le pasa una instantánea que contiene todos los datos en esa ubicación, incluidos los datos secundarios. Si no hay datos, la instantánea devuelta es null .

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

  class LeadersValueListener : public firebase::database::ValueListener {
   public:
    void OnValueChanged(
        const firebase::database::DataSnapshot& snapshot) override {
      // Do something with the data in snapshot...
    }
    void OnCancelled(const firebase::database::Error& error_code,
                     const char* error_message) override {
      LogMessage("ERROR: LeadersValueListener canceled: %d: %s", error_code,
                 error_message);
    }
  };

  // Elsewhere in the code...

  LeadersValueListener* listener = new LeadersValueListener();
  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("Leaders").AddValueListener(listener);

El resultado Future&ltDataSnapshot&gt contiene los datos en la ubicación especificada en la base de datos en el momento del evento. Llamar value() en una instantánea devuelve una Variant que representa los datos.

En este ejemplo, el método OnCancelled también se anula para ver si se cancela la lectura. Por ejemplo, una lectura se puede cancelar si el cliente no tiene permiso para leer desde una ubicación de base de datos de Firebase. La database::Error indicará por qué ocurrió la falla.

clase ChildListener

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 PushChild() o un hijo que se actualiza mediante el método UpdateChildren() . Cada uno de estos juntos puede ser útil para escuchar cambios en un nodo específico en una base de datos. Por ejemplo, un juego podría utilizar estos métodos juntos para monitorear la actividad en los comentarios de una sesión de juego, como se muestra a continuación:

  class SessionCommentsChildListener : public firebase::database::ChildListener {
   public:
    void OnChildAdded(const firebase::database::DataSnapshot& snapshot,
                      const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnChildChanged(const firebase::database::DataSnapshot& snapshot,
                        const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnChildRemoved(
        const firebase::database::DataSnapshot& snapshot) override {
      // Do something with the data in snapshot ...
    }
    void OnChildMoved(const firebase::database::DataSnapshot& snapshot,
                      const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnCancelled(const firebase::database::Error& error_code,
                     const char* error_message) override {
      LogMessage("ERROR: SessionCommentsChildListener canceled: %d: %s",
                 error_code, error_message);
    }
  };

  // elsewhere ....

  SessionCommentsChildListener* listener = new SessionCommentsChildListener();
  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("GameSessionComments").AddChildListener(listener);

La devolución de llamada OnChildAdded se usa normalmente para recuperar una lista de elementos en una base de datos de Firebase. La devolución de llamada OnChildAdded se llama una vez para cada elemento secundario existente y luego nuevamente cada vez que se agrega un elemento secundario nuevo a la ruta especificada. Al oyente se le pasa una instantánea que contiene los datos del nuevo niño.

La devolución de llamada OnChildChanged se llama cada vez que se modifica un nodo secundario. Esto incluye cualquier modificación a los descendientes del nodo hijo. Normalmente se utiliza junto con las llamadas OnChildAdded y OnChildRemoved para responder a cambios en una lista de elementos. La instantánea pasada al oyente contiene los datos actualizados del niño.

La devolución de llamada OnChildRemoved se activa cuando se elimina un niño inmediato. Normalmente se utiliza junto con las devoluciones de llamada OnChildAdded y OnChildChanged . La instantánea pasada a la devolución de llamada contiene los datos del niño eliminado.

La devolución de llamada OnChildMoved se activa cada vez que la llamada OnChildChanged se genera por una actualización que provoca el reordenamiento del niño. Se utiliza con datos ordenados con OrderByChild o OrderByValue .

Ordenar y filtrar datos

Puede utilizar la clase Query de base de datos en tiempo real 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.
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 suscribirte a una tabla de clasificación de puntuación ordenada por puntuación.

  firebase::database::Query query =
    dbRef.GetReference("Leaders").OrderByChild("score");

  // To get the resulting DataSnapshot either use query.GetValue() and poll the
  // future, or use query.AddValueListener() and register to handle the
  // OnValueChanged callback.

Esto define una firebase::Query que, cuando se combina con ValueListener, sincroniza el cliente con la tabla de clasificación en la base de datos, ordenada por la puntuación de cada entrada. Puede leer más sobre cómo estructurar sus datos de manera eficiente en Estructurar su base de datos .

La llamada al método OrderByChild() especifica la clave secundaria para ordenar los resultados. En este caso, los resultados se ordenan por el valor de la "score" de cada niño. 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.
EndAt() Devuelve elementos menores o iguales a la clave o valor especificado según el método de ordenamiento 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 de valores específico.

Incluso cuando solo hay una coincidencia para la consulta, la instantánea sigue siendo una lista; solo contiene un solo elemento.

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 una devolución de llamada determinada. Por ejemplo, si usa LimitToFirst() para establecer un límite de 100, inicialmente solo recibirá hasta 100 devoluciones de llamada OnChildAdded . Si tiene menos de 100 elementos almacenados en su base de datos de Firebase, se activa una devolución de llamada OnChildAdded para cada elemento.

A medida que los elementos cambian, recibe devoluciones de llamada OnChildAdded para los elementos que ingresan a la consulta y devoluciones de llamada OnChildRemoved para los elementos que salen de ella, de modo que el número total permanezca en 100.

Por ejemplo, el siguiente código devuelve la puntuación más alta de una tabla de clasificación:

  firebase::database::Query query =
    dbRef.GetReference("Leaders").OrderByChild("score").LimitToLast(1);

  // To get the resulting DataSnapshot either use query.GetValue() and poll the
  // future, or use query.AddValueListener() and register to handle the
  // OnValueChanged callback.

Filtrar por clave o valor

Puede utilizar StartAt() , EndAt() 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 utiliza OrderByKey() para ordenar sus 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 utiliza el valor del nodo en lugar del valor de una clave secundaria especificada.

Próximos pasos