Получить FIRDatabaseReference
Для чтения или записи данных из базы данных вам необходим экземпляр FIRDatabaseReference
:
Быстрый
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
Списки чтения и письма
Добавить к списку данных
Используйте метод childByAutoId
для добавления данных в список в многопользовательских приложениях. Метод childByAutoId
генерирует уникальный ключ каждый раз, когда новый дочерний элемент добавляется в указанную ссылку Firebase. Используя эти автоматически сгенерированные ключи для каждого нового элемента в списке, несколько клиентов могут добавлять дочерние элементы в одно и то же место в одно и то же время без конфликтов записи. Уникальный ключ, сгенерированный childByAutoId
, основан на временной метке, поэтому элементы списка автоматически упорядочиваются в хронологическом порядке.
Вы можете использовать ссылку на новые данные, возвращаемые методом childByAutoId
, чтобы получить значение автоматически сгенерированного ключа дочернего элемента или задать данные для дочернего элемента. Вызов getKey
для ссылки childByAutoId
возвращает автоматически сгенерированный ключ.
Вы можете использовать эти автоматически сгенерированные ключи для упрощения выравнивания структуры данных. Для получения дополнительной информации см. пример разветвления данных.
Прислушивайтесь к детским событиям
Дочерние события запускаются в ответ на определенные операции, которые происходят с дочерними элементами узла, например, при добавлении нового дочернего элемента с помощью метода childByAutoId
или обновлении дочернего элемента с помощью метода updateChildValues
.
Тип события | Типичное использование |
---|---|
FIRDataEventTypeChildAdded | Извлечь списки элементов или прослушать добавления в список элементов. Это событие запускается один раз для каждого существующего потомка, а затем снова каждый раз, когда новый потомок добавляется к указанному пути. Слушателю передается снимок, содержащий данные нового потомка. |
FIRDataEventTypeChildChanged | Прослушивать изменения элементов в списке. Это событие запускается каждый раз, когда изменяется дочерний узел. Это включает любые изменения потомков дочернего узла. Снимок, переданный прослушивателю событий, содержит обновленные данные для дочернего узла. |
FIRDataEventTypeChildRemoved | Прослушивание элементов, удаляемых из списка. Это событие срабатывает при удалении непосредственного потомка. Снимок, переданный в блок обратного вызова, содержит данные для удаленного потомка. |
FIRDataEventTypeChildMoved | Прослушивание изменений порядка элементов в упорядоченном списке. Это событие срабатывает всякий раз, когда обновление приводит к переупорядочиванию дочернего элемента. Оно используется с данными, упорядоченными с помощью queryOrderedByChild или queryOrderedByValue . |
Каждый из них вместе может быть полезен для прослушивания изменений в определенном узле в базе данных. Например, приложение для социальных блогов может использовать эти методы вместе для мониторинга активности в комментариях к посту, как показано ниже:
Быстрый
// Listen for new comments in the Firebase database commentsRef.observe(.childAdded, with: { (snapshot) -> Void in self.comments.append(snapshot) self.tableView.insertRows( at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) }) // Listen for deleted comments in the Firebase database commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in let index = self.indexOfMessage(snapshot) self.comments.remove(at: index) self.tableView.deleteRows( at: [IndexPath(row: index, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) })
Objective-C
// Listen for new comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) { [self.comments addObject:snapshot]; [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments] ] withRowAnimation:UITableViewRowAnimationAutomatic]; }]; // Listen for deleted comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildRemoved withBlock:^(FIRDataSnapshot *snapshot) { int index = [self indexOfMessage:snapshot]; [self.comments removeObjectAtIndex:index]; [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]] withRowAnimation:UITableViewRowAnimationAutomatic]; }];
Прислушивайтесь к ценностным событиям
Хотя прослушивание дочерних событий является рекомендуемым способом чтения списков данных, существуют ситуации, когда прослушивание событий значений в ссылке на список может быть полезным.
Присоединение наблюдателя FIRDataEventTypeValue
к списку данных вернет весь список данных в виде одного снимка данных, который затем можно будет циклически перебрать для доступа к отдельным дочерним элементам.
Даже если для запроса есть только одно совпадение, снимок все равно является списком; он содержит только один элемент. Чтобы получить доступ к элементу, вам нужно выполнить цикл по результату:
Быстрый
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
Objective-C
[_commentsRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // Loop over children NSEnumerator *children = [snapshot children]; FIRDataSnapshot *child; while (child = [children nextObject]) { // ... } }];
Этот шаблон может быть полезен, когда вы хотите извлечь все дочерние элементы списка за одну операцию, а не прослушивать дополнительные события добавления дочерних элементов.
Сортировка и фильтрация данных
Вы можете использовать класс Realtime Database FIRDatabaseQuery
для извлечения данных, отсортированных по ключу, по значению или по значению дочернего элемента. Вы также можете отфильтровать отсортированный результат по определенному количеству результатов или диапазону ключей или значений.
Сортировать данные
Чтобы получить отсортированные данные, начните с указания одного из методов сортировки, чтобы определить, как будут упорядочены результаты:
Метод | Использование |
---|---|
queryOrderedByKey | Упорядочить результаты по дочерним ключам. |
queryOrderedByValue | Упорядочить результаты по дочерним значениям. |
queryOrderedByChild | Сортировать результаты по значению указанного дочернего ключа или вложенного дочернего пути. |
Вы можете использовать только один метод order-by за раз. Вызов метода order-by несколько раз в одном запросе приводит к ошибке.
В следующем примере показано, как можно получить список лучших публикаций пользователя, отсортированный по количеству звезд:
Быстрый
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
Objective-C
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
Этот запрос извлекает посты пользователя из пути в базе данных на основе его идентификатора пользователя, упорядоченного по количеству звезд, полученных каждым постом. Этот метод использования идентификаторов в качестве ключей индекса называется data fan out, вы можете прочитать больше о нем в разделе Structure Your Database .
Вызов метода queryOrderedByChild
указывает дочерний ключ для сортировки результатов. В этом примере посты сортируются по значению дочернего элемента "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
, указав относительный путь к вложенному дочернему элементу в нашем вызове queryOrderedByChild
.
Быстрый
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
Objective-C
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];
Дополнительную информацию о том, как упорядочиваются другие типы данных, см. в разделе Как упорядочиваются данные запроса .
Фильтрация данных
Для фильтрации данных при построении запроса можно комбинировать любой из методов ограничения или диапазона с методом сортировки.
Метод | Использование |
---|---|
queryLimitedToFirst | Устанавливает максимальное количество элементов, возвращаемых с начала упорядоченного списка результатов. |
queryLimitedToLast | Устанавливает максимальное количество элементов, возвращаемых из конца упорядоченного списка результатов. |
queryStartingAtValue | Возвращает элементы, большие или равные указанному ключу или значению, в зависимости от выбранного метода сортировки. |
queryStartingAfterValue | Возвращает элементы, превышающие указанный ключ или значение, в зависимости от выбранного метода сортировки. |
queryEndingAtValue | Возвращает элементы, меньшие или равные указанному ключу или значению, в зависимости от выбранного метода сортировки. |
queryEndingBeforeValue | Возвращает элементы, меньшие указанного ключа или значения, в зависимости от выбранного метода сортировки. |
queryEqualToValue | Возвращает элементы, равные указанному ключу или значению, в зависимости от выбранного метода сортировки. |
В отличие от методов order-by, вы можете комбинировать несколько функций limit или range. Например, вы можете комбинировать методы queryStartingAtValue
и queryEndingAtValue
чтобы ограничить результаты указанным диапазоном значений.
Ограничить количество результатов
Вы можете использовать методы queryLimitedToFirst
и queryLimitedToLast
, чтобы задать максимальное количество потомков, которые будут синхронизированы для данного обратного вызова. Например, если вы используете queryLimitedToFirst
для установки лимита в 100, вы изначально получите только до 100 обратных вызовов FIRDataEventTypeChildAdded
. Если в вашей базе данных Firebase хранится менее 100 элементов, обратный вызов FIRDataEventTypeChildAdded
срабатывает для каждого элемента.
При изменении элементов вы получаете обратные вызовы FIRDataEventTypeChildAdded
для элементов, которые входят в запрос, и обратные вызовы FIRDataEventTypeChildRemoved
для элементов, которые из него выпадают, так что общее число остается равным 100.
В следующем примере показано, как приложение для ведения блога может получить список из 100 последних сообщений всех пользователей:
Быстрый
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
Objective-C
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];
Фильтр по ключу или значению
Вы можете использовать queryStartingAtValue
, queryStartingAfterValue
, queryEndingAtValue
, queryEndingBeforeValue
и queryEqualToValue
для выбора произвольных начальных, конечных и эквивалентных точек для запросов. Это может быть полезно для разбиения данных на страницы или поиска элементов с потомками, имеющими определенное значение.
Как упорядочиваются данные запроса
В этом разделе объясняется, как данные сортируются каждым из методов сортировки в классе FIRDatabaseQuery
.
queryOrderedByKey
При использовании queryOrderedByKey
для сортировки данных данные возвращаются в порядке возрастания ключа.
- Сначала идут потомки с ключом, который можно проанализировать как 32-битное целое число, отсортированные в порядке возрастания.
- Далее следуют дочерние элементы со строковым значением в качестве ключа, отсортированные лексикографически в порядке возрастания.
queryOrderedByValue
При использовании queryOrderedByValue
дети сортируются по их значению. Критерии упорядочивания такие же, как в queryOrderedByChild
, за исключением того, что вместо значения указанного дочернего ключа используется значение узла.
queryOrderedByChild
При использовании queryOrderedByChild
данные, содержащие указанный дочерний ключ, упорядочиваются следующим образом:
- Сначала идут потомки с
nil
значением для указанного дочернего ключа. - Далее идут дети со значением
false
для указанного дочернего ключа. Если несколько детей имеют значениеfalse
, они сортируются лексикографически по ключу. - Далее идут дети со значением
true
для указанного дочернего ключа. Если несколько детей имеют значениеtrue
, они сортируются лексикографически по ключу. - Далее следуют дети с числовым значением, отсортированные по возрастанию. Если несколько детей имеют одинаковое числовое значение для указанного дочернего узла, они сортируются по ключу.
- Строки идут после чисел и сортируются лексикографически в порядке возрастания. Если несколько дочерних элементов имеют одинаковое значение для указанного дочернего узла, они упорядочиваются лексикографически по ключу.
- Объекты располагаются последними и сортируются лексикографически по ключу в порядке возрастания.
Отсоединить слушателей
Наблюдатели не прекращают автоматически синхронизацию данных, когда вы покидаете ViewController
. Если наблюдатель не удален должным образом, он продолжает синхронизировать данные с локальной памятью и сохраняет все объекты, захваченные в замыкании обработчика событий, что может привести к утечкам памяти. Когда наблюдатель больше не нужен, удалите его, передав связанный FIRDatabaseHandle
методу removeObserverWithHandle
.
При добавлении блока обратного вызова к ссылке возвращается FIRDatabaseHandle
. Эти дескрипторы можно использовать для удаления блока обратного вызова.
Если в ссылку на базу данных добавлено несколько слушателей, каждый слушатель вызывается при возникновении события. Чтобы остановить синхронизацию данных в этом месте, необходимо удалить всех наблюдателей в этом месте, вызвав метод removeAllObservers
.
Вызов removeObserverWithHandle
или removeAllObservers
для прослушивателя не приводит к автоматическому удалению прослушивателей, зарегистрированных на его дочерних узлах; необходимо также отслеживать эти ссылки или дескрипторы, чтобы удалить их.