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

В этом документе описаны основы получения данных, а также способы упорядочивания и фильтрации данных 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 => {
        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 .

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

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

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

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

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

Одновременно можно использовать только один метод 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() Возвращает элементы, равные указанному ключу или значению, в зависимости от выбранного метода упорядочения.

В отличие от методов упорядочивания, вы можете комбинировать несколько функций ограничения или диапазона. Например, вы можете объединить методы 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() , за исключением того, что вместо значения указанного дочернего ключа используется значение узла.