Извлечение данных

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

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

Прежде чем использовать Realtime Database , вам необходимо:

  • Зарегистрируйте свой проект Unity и настройте его для использования Firebase.

    • Если ваш проект Unity уже использует Firebase, значит, он уже зарегистрирован и настроен для Firebase.

    • Если у вас нет проекта Unity, вы можете загрузить пример приложения .

  • Добавьте Firebase Unity SDK (в частности, FirebaseDatabase.unitypackage ) в ваш проект Unity.

Обратите внимание, что добавление Firebase в ваш проект Unity включает в себя выполнение задач как в консоли Firebase , так и в вашем открытом проекте Unity (например, вы загружаете файлы конфигурации Firebase из консоли, а затем перемещаете их в ваш проект Unity).

Извлечение данных

Данные Firebase извлекаются либо однократным вызовом GetValueAsync(), либо путём присоединения к событию в ссылке FirebaseDatabase . Прослушиватель событий вызывается один раз для получения начального состояния данных и затем каждый раз при их изменении.

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

Для чтения данных из базы данных вам необходим экземпляр 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;
  }
}

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

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

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

Следите за событиями

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

Событие Типичное использование
ValueChanged Чтение и прослушивание изменений во всем содержимом пути.
ChildAdded Извлекайте списки элементов или отслеживайте их добавление. Рекомендуется использовать с ChildChanged и ChildRemoved для отслеживания изменений в списках.
ChildChanged Отслеживайте изменения элементов в списке. Используйте с ChildAdded и ChildRemoved для отслеживания изменений в списках.
ChildRemoved Отслеживает удаление элементов из списка. Используйте с ChildAdded и ChildChanged для отслеживания изменений в списках.
ChildMoved Отслеживайте изменения порядка элементов в упорядоченном списке. События ChildMoved всегда следуют за событием ChildChanged , которое привело к изменению порядка элементов (в соответствии с текущим методом сортировки).

Событие ValueChanged

Событие ValueChanged можно использовать для подписки на изменения содержимого по заданному пути. Это событие срабатывает один раз при подключении прослушивателя и затем каждый раз при изменении данных, включая дочерние. В функцию обратного вызова события передаётся снимок, содержащий все данные в этом месте, включая дочерние. Если данные отсутствуют, возвращается снимок, равный null .

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

      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 содержит объект DataSnapshot , содержащий данные в указанном месте базы данных на момент события. Вызов Value для снимка возвращает Dictionary<string, object> представляющий данные. Если в указанном месте данные отсутствуют, вызов Value возвращает null .

В этом примере также проверяется args.DatabaseError на предмет отмены чтения. Например, чтение может быть отменено, если у клиента нет разрешения на чтение из расположения базы данных Firebase. Ошибка DatabaseError укажет причину сбоя.

Позже вы сможете отписаться от события, используя любую DatabaseReference с тем же путём. Экземпляры DatabaseReference являются временными и могут рассматриваться как способ доступа к любому пути и запросу.

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

Детские мероприятия

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

      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
    }

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

Событие ChildChanged возникает при каждом изменении дочернего узла. Это включает любые изменения потомков дочернего узла. Обычно оно используется вместе с событиями ChildAdded и ChildRemoved для реагирования на изменения в списке элементов. Снимок, передаваемый прослушивателю событий, содержит обновлённые данные для дочернего узла.

Событие ChildRemoved срабатывает при удалении непосредственного дочернего элемента. Обычно оно используется вместе с функциями обратного вызова ChildAdded и ChildChanged . Снимок экрана, передаваемый в функцию обратного вызова события, содержит данные об удаленном дочернем элементе.

Событие ChildMoved срабатывает каждый раз, когда событие ChildChanged возникает при обновлении, вызывающем переупорядочивание дочернего элемента. Оно используется с данными, упорядоченными с помощью OrderByChild или OrderByValue .

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

Вы можете использовать класс Realtime Database Query для извлечения данных, отсортированных по ключу, значению или значению дочернего элемента. Вы также можете отфильтровать отсортированный результат по определённому количеству результатов или диапазону ключей или значений.

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

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

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

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

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

      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
    }

Это определяет запрос, который в сочетании с прослушивателем событий valuechanged синхронизирует клиент с таблицей лидеров в базе данных, упорядоченной по баллам каждой записи. Подробнее об эффективной структуризации данных можно узнать в статье «Структурирование базы данных» .

Вызов метода OrderByChild() указывает дочерний ключ, по которому следует упорядочить результаты. В этом случае результаты сортируются по значению "score" для каждого дочернего элемента. Подробнее об упорядочивании других типов данных см. в разделе «Как упорядочиваются данные запроса ».

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

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

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

В отличие от методов order-by, вы можете комбинировать несколько функций ограничения или диапазона. Например, можно объединить методы StartAt() и EndAt() чтобы ограничить результаты заданным диапазоном значений.

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

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

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

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

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

      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
    }

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

Вы можете использовать StartAt() , EndAt() и EqualTo() для выбора произвольных начальных, конечных и эквивалентных точек для запросов. Это может быть полезно для разбиения данных на страницы или поиска элементов с дочерними элементами, имеющими определённое значение.

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

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

OrderByChild

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

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

OrderByKey

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

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

OrderByValue

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