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

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.

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

Прежде чем вы начнете

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

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

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

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

  • Добавьте SDK Firebase Unity (в частности, 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 к базе данных в реальном времени для извлечения данных, отсортированных по ключу, по значению или по значению дочернего элемента. Вы также можете отфильтровать отсортированный результат по определенному количеству результатов или диапазону ключей или значений.

Сортировать данные

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

Метод Применение
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() для выбора произвольной начальной, конечной точки и точки эквивалентности для запросов. Это может быть полезно для разбиения данных на страницы или поиска элементов с дочерними элементами, имеющими определенное значение.

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

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

OrderByChild

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

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

OrderByKey

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

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

OrderByValue

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