Получение данных с помощью базы данных Firebase Realtime для C++

В этом документе рассматриваются основы извлечения данных, а также способы упорядочивания и фильтрации данных в Firebase.

Прежде чем начать

Убедитесь, что ваше приложение настроено и вы можете получить доступ к базе данных, как описано в руководстве Get Started .

Получение данных

Firebase data is retrieved by either a one time call to GetValue() or attaching to a ValueListener on a FirebaseDatabase reference. The value listener is called once for the initial state of the data and again anytime the data changes.

Получить ссылку на базу данных

Для записи данных в базу данных вам потребуется экземпляр класса DatabaseReference :

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

Прочитайте данные один раз

Метод GetValue() позволяет один раз прочитать статический снимок содержимого по указанному пути. Результатом выполнения задачи станет снимок, содержащий все данные в этом месте, включая данные дочерних элементов. Если данных нет, возвращается значение null .

  firebase::Future&ltfirebase::database::DataSnapshot&gt result =
    dbRef.GetReference("Leaders").GetValue();

At the point the request has been made but we have to wait for the Future to complete before we can read the value. Since games typically run in a loop, and are less callback driven than other applications, you'll typically poll for completion.

  // 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...
    }
  }

Здесь показана базовая проверка ошибок; для получения дополнительной информации о проверке ошибок и способах определения готовности результата см. справочник по firebase::Future.

Слушайте новости о событиях

Вы можете добавить слушатели, которые будут подписываться на изменения данных:

Базовый класс ValueListener

Перезвонить Типичное использование
OnValueChanged Внимательно читайте и прислушивайтесь к изменениям во всем содержимом пути.

Базовый класс OnChildListener

OnChildAdded Получайте списки элементов или отслеживайте добавления элементов в список. Рекомендуется использовать с OnChildChanged и OnChildRemoved для мониторинга изменений в списках.
OnChildChanged Отслеживайте изменения элементов в списке. Используйте с OnChildAdded и OnChildRemoved для мониторинга изменений в списках.
OnChildRemoved Отслеживайте удаление элементов из списка. Используйте с OnChildAdded и OnChildChanged для мониторинга изменений в списках.
OnChildMoved Listen for changes to the order of items in an ordered list. OnChildMoved callbacks always follow the OnChildChanged callbacks due to the item's order changing (based on your current order-by method).

Класс ValueListener

You can use the OnValueChanged callbacks to subscribe to changes to the contents at a given path. This callback is triggered once when the listener is attached and again every time the data, including children, changes. The callback is passed a snapshot containing all data at that location, including child data. If there is no data, the snapshot returned is null .

Следующий пример демонстрирует игру, в которой результаты таблицы лидеров извлекаются из базы данных:

  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&ltfirebase::database::DataSnapshot&gt result =
    dbRef.GetReference("Leaders").AddValueListener(listener);

Результат Future&ltDataSnapshot&gt содержит данные, находящиеся в указанном месте базы данных на момент события. Вызов метода value() для снимка возвращает Variant представляющий эти данные.

In this example, the OnCancelled method is also overridden to see if the read is canceled. For example, a read can be canceled if the client doesn't have permission to read from a Firebase database location. The database::Error will indicate why the failure occurred.

Класс ChildListener

События, связанные с дочерними узлами, запускаются в ответ на определенные операции, происходящие с дочерними узлами, например, добавление нового дочернего узла с помощью метода PushChild() или обновление дочернего узла с помощью метода UpdateChildren() . Каждый из этих методов в совокупности может быть полезен для отслеживания изменений в конкретном узле базы данных. Например, игра может использовать эти методы вместе для мониторинга активности в комментариях игровой сессии, как показано ниже:

  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&ltfirebase::database::DataSnapshot&gt result =
    dbRef.GetReference("GameSessionComments").AddChildListener(listener);

The OnChildAdded callback is typically used to retrieve a list of items in a Firebase database. The OnChildAdded callback is called once for each existing child and then again every time a new child is added to the specified path. The listener is passed a snapshot containing the new child's data.

Функция обратного вызова OnChildChanged вызывается всякий раз, когда изменяется дочерний узел. Это включает в себя любые изменения потомков дочернего узла. Обычно она используется совместно с вызовами OnChildAdded и OnChildRemoved для реагирования на изменения списка элементов. Снимок, передаваемый слушателю, содержит обновленные данные для дочернего узла.

The OnChildRemoved callback is triggered when an immediate child is removed. It is typically used in conjunction with the OnChildAdded and OnChildChanged callbacks. The snapshot passed to the callback contains the data for the removed child.

The OnChildMoved callback is triggered whenever the OnChildChanged call is raised by an update that causes reordering of the child. It is used with data that is ordered with OrderByChild or OrderByValue .

Сортировка и фильтрация данных

С помощью класса Realtime Database Query можно получать данные, отсортированные по ключу, по значению или по значению дочернего элемента. Также можно отфильтровать отсортированный результат, выбрав определенное количество результатов или диапазон ключей или значений.

Сортировка данных

Для получения отсортированных данных сначала укажите один из методов сортировки, чтобы определить, как будут упорядочены результаты:

Метод Использование
OrderByChild() Сортировать результаты по значению указанного дочернего ключа.
OrderByKey() Сортировать результаты по дочерним ключам.
OrderByValue() Сортировать результаты по значениям дочерних элементов.

Одновременно можно использовать только один метод сортировки. Многократный вызов метода сортировки в одном запросе приведет к ошибке.

Следующий пример демонстрирует, как можно подписаться на таблицу лидеров по результатам матчей, отсортированную по набранным очкам.

  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.

This defines a firebase::Query that when combined with a ValueListener synchronizes the client with the leaderboard in the database, ordered by the score of each entry. You can read more about structuring your data efficiently in Structure Your Database .

The call to the OrderByChild() method specifies the child key to order the results by. In this case, results are sorted by the value of the "score" value in each child. For more information on how other data types are ordered, see How query data is ordered .

Фильтрация данных

Для фильтрации данных при построении запроса можно комбинировать любой из методов ограничения или диапазона с методом сортировки.

Метод Использование
LimitToFirst() Устанавливает максимальное количество элементов, возвращаемых с начала упорядоченного списка результатов.
LimitToLast() Устанавливает максимальное количество элементов, возвращаемых с конца упорядоченного списка результатов.
StartAt() Возвращает элементы, большие или равные указанному ключу или значению, в зависимости от выбранного метода сортировки.
EndAt() Возвращает элементы, меньшие или равные указанному ключу или значению в зависимости от выбранного метода сортировки.
EqualTo() Возвращает элементы, равные указанному ключу или значению в зависимости от выбранного метода сортировки.

Unlike the order-by methods, you can combine multiple limit or range functions. For example, you can combine the StartAt() and EndAt() methods to limit the results to a specified range of values.

Даже если для запроса найдено только одно совпадение, снимок все равно представляет собой список; он просто содержит один элемент.

Ограничьте количество результатов

Методы LimitToFirst() и LimitToLast() позволяют установить максимальное количество дочерних элементов, синхронизируемых для данного коллбэка. Например, если вы используете LimitToFirst() для установки лимита в 100, вы изначально получите только до 100 коллбэков OnChildAdded . Если в вашей базе данных Firebase хранится менее 100 элементов, коллбэк OnChildAdded будет срабатывать для каждого элемента.

По мере изменения элементов вы получаете коллбэки OnChildAdded для элементов, которые попадают в запрос, и коллбэки OnChildRemoved для элементов, которые из него выпадают, так что общее количество остается равным 100.

Например, приведенный ниже код возвращает лучший результат из таблицы лидеров:

  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.

Фильтрация по ключу или значению

You can use StartAt() , EndAt() , and EqualTo() to choose arbitrary starting, ending, and equivalence points for queries. This can be useful for paginating data or finding items with children that have a specific value.

Как упорядочиваются данные запроса

В этом разделе объясняется, как данные сортируются каждым из методов ORDER BY в классе Query .

OrderByChild

При использовании функции OrderByChild() данные, содержащие указанный дочерний ключ, упорядочиваются следующим образом:

  1. В первую очередь идут дочерние элементы, у которых указанный ключ дочернего элемента имеет null значение.
  2. Далее следуют дочерние элементы со значением false для указанного ключа дочернего элемента. Если несколько дочерних элементов имеют значение false , они сортируются лексикографически по ключу.
  3. Далее следуют дочерние элементы, у которых для указанного ключа дочернего элемента значение равно true . Если несколько дочерних элементов имеют значение true , они сортируются лексикографически по ключу.
  4. Далее следуют дочерние узлы с числовым значением, отсортированные в порядке возрастания. Если несколько дочерних узлов имеют одинаковое числовое значение для указанного дочернего узла, они сортируются по ключу.
  5. Строки следуют за числами и сортируются лексикографически в порядке возрастания. Если несколько дочерних узлов имеют одинаковое значение для указанного дочернего узла, они упорядочиваются лексикографически по ключу.
  6. Объекты располагаются в самом конце и сортируются лексикографически по ключу в порядке возрастания.

OrderByKey

При использовании OrderByKey() для сортировки данных, данные возвращаются в порядке возрастания по ключу.

  1. В порядке возрастания первыми идут дочерние элементы, ключ которых может быть интерпретирован как 32-битное целое число.
  2. Далее следуют дети, у которых в качестве ключа используется строковое значение, отсортированные лексикографически в порядке возрастания.

OrderByValue

При использовании OrderByValue() дочерние узлы упорядочиваются по их значению. Критерии сортировки такие же, как и в OrderByChild() , за исключением того, что вместо значения указанного ключа дочернего узла используется значение самого узла.

Следующие шаги