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

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

Подготовка

Чтобы использовать Realtime Database, вам необходимо:

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

    • Если в проекте уже используется Firebase, можете пропустить этот шаг.

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

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

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

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

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

Как получить DatabaseReference

Чтобы считывать данные из базы данных, вам понадобится экземпляр 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, возникнет ошибка.

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

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