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

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

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

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

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

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

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