Получение ссылки на базу данных
Чтобы читать данные из базы данных или записывать их в нее, вам нужен экземпляр DatabaseReference:
DatabaseReference ref = FirebaseDatabase.instance.ref();
Списки для чтения и записи
Добавление данных в список
Используйте метод push(), чтобы добавить данные в список в многопользовательских приложениях.
Метод push() генерирует уникальный ключ каждый раз, когда в указанную ссылку Firebase добавляется новый дочерний элемент. Используя эти автоматически сгенерированные ключи для каждого нового элемента в списке, несколько клиентов могут одновременно добавлять дочерние элементы в одно и то же место без конфликтов записи. Уникальный ключ, созданный push(), основан на временной метке, поэтому элементы списка автоматически упорядочиваются в хронологическом порядке.
Вы можете использовать ссылку на новые данные, возвращенные методом push(), чтобы получить значение автоматически сгенерированного ключа дочернего элемента или задать данные для дочернего элемента. Свойство .key ссылки push() содержит автоматически сгенерированный ключ.
Эти автоматически созданные ключи можно использовать для упрощения структуры данных. Подробнее о размножении данных…
Например, метод push() можно использовать, чтобы добавить новую запись в список записей в социальном приложении:
DatabaseReference postListRef = FirebaseDatabase.instance.ref("posts");
DatabaseReference newPostRef = postListRef.push();
newPostRef.set({
// ...
});
Как отслеживать дочерние события
Дочерние события запускаются в ответ на определенные операции, которые происходят с дочерними элементами узла, например добавление нового дочернего элемента с помощью метода push() или обновление дочернего элемента с помощью метода update().
| Событие | Типичные сценарии использования |
|---|---|
onChildAdded |
Получать списки объектов или слушать дополнения к списку объектов. Это событие запускается один раз для каждого существующего дочернего элемента, а затем каждый раз, когда новый дочерний элемент добавляется по указанному пути. Прослушиватель получает снимок, содержащий данные нового дочернего объекта. |
onChildChanged |
Отслеживать изменения элементов в списке. Это событие активируется при каждом изменении дочернего узла. в том числе изменения дочерних узлов. Объект snapshot, переданный прослушивателю событий, содержит обновленные данные для дочернего узла. |
onChildRemoved |
Прослушивание событий удаления элементов из списка. Это событие активируется при удалении непосредственного дочернего элемента.Снимок, переданный в блок обратного вызова, содержит данные удаленного дочернего элемента. |
onChildMoved |
Отслеживать изменения в порядке элементов в упорядоченном списке. События onChildMoved всегда следуют за событием onChildChanged, которое привело к изменению порядка элементов (в зависимости от текущего способа сортировки). |
Каждый из них может быть полезен для прослушивания изменений в определенном узле базы данных. Например, в приложении для ведения блогов эти методы можно использовать вместе, чтобы отслеживать активность в комментариях к записи, как показано ниже.
final commentsRef = FirebaseDatabase.instance.ref("post-comments/$postId");
commentsRef.onChildAdded.listen((event) {
// A new comment has been added, so add it to the displayed list.
});
commentsRef.onChildChanged.listen((event) {
// A comment has changed; use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
});
commentsRef.onChildRemoved.listen((event) {
// A comment has been removed; use the key to determine if we are displaying
// this comment and if so remove it.
});
Как отслеживать события ценности
Хотя для чтения списков данных рекомендуется прослушивать дочерние события, в некоторых ситуациях полезно прослушивать события значений в ссылке на список.
Прикрепление прослушивателя value к списку данных вернет весь список данных в виде одного снимка, который затем можно зациклить для доступа к отдельным дочерним элементам.
Даже если запросу соответствует только один документ, снимок все равно будет списком, просто с одним элементом. Чтобы получить доступ к элементу, нужно выполнить цикл по результату:
myTopPostsQuery.onValue.listen((event) {
for (final child in event.snapshot.children) {
// Handle the post.
}
}, onError: (error) {
// Error.
});
Этот шаблон может быть полезен, когда вы хотите получить все дочерние элементы списка за одну операцию, а не прослушивать дополнительные события добавления дочерних элементов.
Сортировка и фильтрация данных
Класс Query позволяет получать данные, отсортированные по ключу, значению или значению дочернего элемента. Вы также можете отфильтровать отсортированный результат по определенному количеству результатов или диапазону ключей или значений.
Сортировка данных
Чтобы получить отсортированные данные, сначала укажите один из способов сортировки, определяющий порядок результатов:
| Метод | Использование |
|---|---|
orderByChild() |
Упорядочить результаты по значению указанного дочернего ключа или вложенного дочернего пути. |
orderByKey() |
Упорядочить результаты по дочерним ключам. |
orderByValue() |
Упорядочить результаты по дочерним значениям. |
Одновременно можно использовать только один способ сортировки. Если вызвать способ сортировки несколько раз в одном запросе, возникнет ошибка.
В примере ниже показано, как получить список лучших записей пользователя, отсортированных по количеству звезд.
final myUserId = FirebaseAuth.instance.currentUser?.uid;
final topUserPostsRef = FirebaseDatabase.instance
.ref("user-posts/$myUserId")
.orderByChild("starCount");
Этот запрос в сочетании с дочерним прослушивателем синхронизирует клиент с записями пользователя из пути в базе данных на основе его идентификатора пользователя, упорядоченными по количеству звезд, полученных каждой записью. Этот метод использования идентификаторов в качестве ключей индекса называется развертыванием данных. Подробнее о нем можно прочитать в статье Структурирование базы данных.
Вызов метода orderByChild() указывает дочерний ключ, по которому нужно упорядочить результаты. В этом случае записи сортируются по значению дочернего элемента "starCount". Запросы также можно упорядочивать по вложенным дочерним элементам, если у вас есть данные, которые выглядят следующим образом:
"posts": {
"ts-functions": {
"metrics": {
"views" : 1200000,
"likes" : 251000,
"shares": 1200,
},
"title" : "Why you should use TypeScript for writing Cloud Functions",
"author": "Doug",
},
"android-arch-3": {
"metrics": {
"views" : 900000,
"likes" : 117000,
"shares": 144,
},
"title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
"author": "Doug",
}
},
В этом случае мы можем упорядочить элементы списка по значениям, вложенным в ключ metrics, указав относительный путь к вложенному дочернему элементу в вызове orderByChild().
final mostViewedPosts =
FirebaseDatabase.instance.ref('posts').orderByChild('metrics/views');
Подробнее о том, как упорядочиваются данные запросов…
Фильтрация данных
Чтобы отфильтровать данные, при создании запроса можно комбинировать любые методы ограничения или диапазона со способом сортировки.
| Метод | Использование |
|---|---|
limitToFirst() |
Задает максимальное количество элементов, которые будут возвращены из начала упорядоченного списка результатов. |
limitToLast() |
Задает максимальное количество элементов, которые будут возвращены из конца упорядоченного списка результатов. |
startAt() |
Возвращает элементы, которые больше или равны указанному ключу или значению, в зависимости от выбранного способа сортировки. |
startAfter() |
Возвращает объекты, которые больше указанного ключа или значения в зависимости от выбранного способа сортировки. |
endAt() |
Возвращает элементы, которые меньше или равны указанному ключу или значению, в зависимости от выбранного способа сортировки. |
endBefore() |
Возвращает объекты, которые меньше указанного ключа или значения в зависимости от выбранного способа сортировки. |
equalTo() |
Возвращает элементы, равные указанному ключу или значению, в зависимости от выбранного способа сортировки. |
В отличие от способов сортировки, вы можете комбинировать несколько функций ограничения или диапазона.
Например, вы можете объединить методы startAt() и endAt(), чтобы ограничить результаты определенным диапазоном значений.
Ограничение количества результатов
Вы можете использовать методы limitToFirst() и limitToLast(), чтобы задать максимальное количество дочерних элементов, которые будут синхронизированы для определенного события. Например, если вы используете limitToFirst(), чтобы установить ограничение в 100, то сначала вы получите только до 100 событий onChildAdded. Если в базе данных Firebase хранится менее 100 объектов, то для каждого из них активируется событие onChildAdded.
По мере изменения элементов вы будете получать события onChildAdded для элементов, которые входят в запрос, и события onChildRemoved для элементов, которые выпадают из него, чтобы общее количество оставалось равным 100.
В следующем примере показано, как приложение для ведения блогов определяет запрос для получения списка из 100 последних сообщений всех пользователей:
final recentPostsRef = FirebaseDatabase.instance.ref('posts').limitToLast(100);
В этом примере определяется только запрос. Чтобы синхронизировать данные, необходимо подключить прослушиватель.
Фильтр по ключу или значению
Вы можете использовать операторы startAt(), startAfter(), endAt(), endBefore() и equalTo(), чтобы задавать произвольные начальные, конечные и эквивалентные точки для запросов. Это может быть полезно для разбивки данных на страницы или поиска элементов с дочерними элементами, имеющими определенное значение.
Как упорядочиваются данные запроса
В этом разделе объясняется, как сортируются данные при использовании каждого из способов сортировки в классе Query.
orderByChild
При использовании orderByChild() данные, содержащие указанный дочерний ключ, упорядочиваются следующим образом:
- Дочерние элементы с меньшим значением
nullдля указанного дочернего ключа будут показаны первыми. - Затем следуют дочерние элементы со значением
falseдля указанного дочернего ключа. Если у нескольких дочерних элементов значениеfalseсовпадает, они сортируются по ключу в лексикографическом порядке. - Затем следуют дочерние элементы со значением
trueдля указанного дочернего ключа. Если у нескольких дочерних элементов значениеtrue, они сортируются по ключу в лексикографическом порядке. - Затем идут дочерние элементы с числовыми значениями, отсортированные по возрастанию. Если у нескольких дочерних узлов одинаковое числовое значение, они сортируются по ключу.
- Строки следуют за числами и сортируются в лексикографическом порядке по возрастанию. Если у нескольких дочерних узлов одинаковое значение для указанного дочернего узла, они упорядочиваются лексикографически по ключу.
- Объекты указываются в последнюю очередь и сортируются в лексикографическом порядке по ключу по возрастанию.
orderByKey
При использовании orderByKey() для сортировки данные возвращаются в порядке возрастания по ключу.
- Сначала идут дочерние узлы с ключом, который можно обработать как 32-битное целое число, отсортированные по возрастанию.
- Затем идут дочерние элементы со строковым значением в качестве ключа, отсортированные в лексикографическом порядке по возрастанию.
orderByValue
При использовании orderByValue() дочерние элементы упорядочиваются по значению. Критерии сортировки те же, что и в orderByChild(), но вместо значения указанного дочернего ключа используется значение узла.
Отключить прослушиватели
Чтобы удалить обратные вызовы, вызовите метод off() для ссылки на базу данных Firebase.
Чтобы удалить один прослушиватель, передайте его в качестве параметра в off().
Вызов off() для местоположения без аргументов удаляет всех слушателей в этом местоположении.
Вызов off() для родительского прослушивателя не приводит к автоматическому удалению прослушивателей, зарегистрированных для дочерних узлов. Чтобы удалить обратный вызов, необходимо также вызвать off() для всех дочерних прослушивателей.