В этом документе рассматриваются основы извлечения данных, а также способы упорядочивания и фильтрации данных в 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 , которое вызвало изменение порядка элементов (в зависимости от используемого метода сортировки). |
Событие ValueChange
Вы можете использовать событие 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() | Сортировать результаты по значениям дочерних элементов. |
Одновременно можно использовать только один метод сортировки. Многократный вызов метода сортировки в одном запросе приведет к ошибке.
Следующий пример демонстрирует, как можно подписаться на таблицу лидеров по очкам.
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() для выбора произвольных начальных, конечных и эквивалентных точек для запросов. Это может быть полезно для постраничной навигации данных или поиска элементов с дочерними элементами, имеющими определенное значение.
Как упорядочиваются данные запроса
В этом разделе объясняется, как данные сортируются каждым из методов ORDER BY в классе Query .
OrderByChild
При использовании функции OrderByChild() данные, содержащие указанный дочерний ключ, упорядочиваются следующим образом:
- В первую очередь идут дочерние элементы, у которых указанный ключ дочернего элемента имеет
nullзначение. - Далее следуют дочерние элементы со значением
falseдля указанного ключа дочернего элемента. Если несколько дочерних элементов имеют значениеfalse, они сортируются лексикографически по ключу. - Далее следуют дочерние элементы, у которых для указанного ключа дочернего элемента значение равно
true. Если несколько дочерних элементов имеют значениеtrue, они сортируются лексикографически по ключу. - Далее следуют дочерние узлы с числовым значением, отсортированные в порядке возрастания. Если несколько дочерних узлов имеют одинаковое числовое значение для указанного дочернего узла, они сортируются по ключу.
- Строки следуют за числами и сортируются лексикографически в порядке возрастания. Если несколько дочерних узлов имеют одинаковое значение для указанного дочернего узла, они упорядочиваются лексикографически по ключу.
- Объекты располагаются в самом конце и сортируются лексикографически по ключу в порядке возрастания.
OrderByKey
При использовании OrderByKey() для сортировки данных, данные возвращаются в порядке возрастания по ключу.
- В порядке возрастания первыми идут дочерние элементы, ключ которых может быть интерпретирован как 32-битное целое число.
- Далее следуют дети, у которых в качестве ключа используется строковое значение, отсортированные лексикографически в порядке возрастания.
OrderByValue
При использовании OrderByValue() дочерние узлы упорядочиваются по их значению. Критерии сортировки такие же, как и в OrderByChild() , за исключением того, что вместо значения указанного ключа дочернего узла используется значение самого узла.