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

Чтение данных с помощью GET

Мы можем считывать данные из нашей базы данных Firebase, отправляя GET запрос к ее URL-адресу. Давайте продолжим наш пример с блогом из предыдущего раздела и прочитаем все данные из наших записей в блоге:

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'

Успешный запрос будет обозначен HTTP-кодом состояния 200 OK , а ответ будет содержать данные, которые мы получаем.

Добавление параметров URI

REST API принимает несколько параметров запроса при чтении данных из нашей базы данных Firebase. Ниже перечислены наиболее часто используемые параметры. Полный список см. в справочнике REST API .

аутентификация

Параметр запроса auth обеспечивает доступ к данным, защищенным Firebase Realtime Database Security Rules , и поддерживается всеми типами запросов. Аргументом может быть либо секрет вашего приложения Firebase, либо токен аутентификации, как описано в разделе « Пользователи в проектах Firebase» . В следующем примере мы отправляем GET запрос с параметром auth , где CREDENTIAL — это либо секрет вашего приложения Firebase, либо токен аутентификации:

curl 'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

печать

Указание параметра print=pretty возвращает данные в удобочитаемом формате.

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'

Указание параметра print=silent в случае успеха приводит к ошибке 204 No Content .

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=silent'

перезвонить

Для выполнения REST-запросов из веб-браузера между доменами можно использовать JSONP для обертывания ответа в функцию обратного вызова JavaScript. Добавьте callback= , чтобы REST API обернул возвращаемые данные в указанную вами функцию обратного вызова. Например:

<script>
  function gotData(data) {
    console.log(data);
  }
</script>
<script src="https://docs-examples.firebaseio.com/fireblog/posts.json?callback=gotData">

мелкий

Это расширенная функция, разработанная для работы с большими наборами данных без необходимости загрузки всего содержимого. Для её использования добавьте параметр shallow=true . Это ограничит глубину возвращаемых данных. Если данные по указанному адресу представляют собой примитив JSON (строка, число или логическое значение), будет возвращено только его значение. Если снимок данных по указанному адресу представляет собой объект JSON, значения для каждого ключа будут усечены до значения true . Например, используя данные ниже:

{
  "message": {
    "user": {
      "name": "Chris"
    },
    "body": "Hello!"
  }
}

// A request to /message.json?shallow=true
// would return the following:
{
  "user": true,
  "body": true
}

// A request to /message/body.json?shallow=true
// would simply return:
"Hello!"

Попробуйте выполнить этот запрос curl :

curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?shallow=true&print=pretty'

таймаут

Используйте это для ограничения времени чтения на стороне сервера. Если запрос на чтение не завершается в отведенное время, он заканчивается ошибкой HTTP 400. Это особенно полезно, когда вы ожидаете небольшой объем передаваемых данных и не хотите слишком долго ждать получения потенциально огромного поддерева. Фактическое время чтения может варьироваться в зависимости от размера данных и кэширования.

Укажите timeouts в следующем формате: 3ms , 3s или 3min , указав число и единицу измерения. Если значение не указано, будет применено максимальное timeout 15min . Если timeout не является положительным или превышает максимальное, запрос будет отклонен с ошибкой HTTP 400. В следующем примере GET запрос включает timeout в 10 секунд.

curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?timeout=10s'

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

Мы можем создавать запросы для фильтрации данных на основе различных факторов. Для начала вы указываете, как хотите фильтровать данные, используя параметр orderBy . Затем вы комбинируете orderBy с любым из пяти других параметров: limitToFirst , limitToLast , startAt , endAt и equalTo .

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

{
  "lambeosaurus": {
    "height": 2.1,
    "length": 12.5,
    "weight": 5000
  },
  "stegosaurus": {
    "height": 4,
    "length": 9,
    "weight": 2500
  }
}

Фильтрация данных может осуществляться тремя способами: по дочернему ключу , по ключу или по значению . Запрос начинается с одного из этих параметров, а затем должен быть объединен с одним или несколькими из следующих параметров: startAt , endAt , limitToFirst , limitToLast или equalTo .

Фильтрация по указанному дочернему ключу.

Мы можем фильтровать узлы по общему ключу дочернего элемента, передав этот ключ параметру orderBy . Например, чтобы получить всех динозавров с высотой больше 3, мы можем сделать следующее:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'

Любой узел, не имеющий ключа "дочерний элемент", по которому выполняется фильтрация, будет отсортирован со значением null . Подробную информацию о порядке упорядочивания данных см. в разделе "Как упорядочиваются данные" .

Firebase также поддерживает запросы, упорядоченные по глубоко вложенным дочерним элементам, а не только по элементам на один уровень ниже. Это полезно, если у вас есть глубоко вложенные данные, подобные этим:

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
      "weight": 5000
    }
  },
  "stegosaurus": {
    "dimensions": {
      "height" : 4,
      "length" : 9,
      "weight" : 2500
    }
  }
}

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

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="dimensions/height"&startAt=3&print=pretty'

Запросы могут фильтровать только по одному ключу за раз. Многократное использование параметра orderBy в одном запросе приводит к ошибке.

Фильтрация по ключу

Мы также можем фильтровать узлы по их ключам, используя параметр orderBy="$key" . Следующий пример извлекает всех динозавров, чье имя начинается с буквы a до m :

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="a"&endAt="m"&print=pretty'

Фильтрация по значению

Мы можем фильтровать узлы по значению их дочерних ключей, используя параметр orderBy="$value" . Допустим, динозавры устраивают спортивные соревнования, и мы отслеживаем их результаты в следующем формате:

{
  "scores": {
    "bruhathkayosaurus": 55,
    "lambeosaurus": 21,
    "linhenykus": 80,
    "pterodactyl": 93,
    "stegosaurus": 5,
    "triceratops": 22
  }
}

Чтобы получить список всех динозавров с рейтингом выше 50, мы можем сделать следующий запрос:

curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&startAt=50&print=pretty'

См. раздел «Как упорядочиваются данные» для объяснения того, как сортируются значения null , boolean, string и object при использовании orderBy="$value" .

Сложная фильтрация

Мы можем комбинировать несколько параметров для построения более сложных запросов.

Ограничение запросов

Параметры limitToFirst и limitToLast используются для установки максимального количества дочерних элементов, для которых будут получены данные. Если мы установим лимит в 100, мы получим данные только для 100 соответствующих дочерних элементов. Если в нашей базе данных хранится менее 100 сообщений, мы получим данные для каждого дочернего элемента. Однако, если у нас более 100 сообщений, мы получим данные только для 100 из них. Это будут первые 100 упорядоченных сообщений, если мы используем limitToFirst , или последние 100 упорядоченных сообщений, если мы используем limitToLast .

Используя нашу базу данных фактов о динозаврах и orderBy , мы можем найти двух самых тяжелых динозавров:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="weight"&limitToLast=2&print=pretty'

Аналогичным образом, мы можем найти двух самых коротких динозавров, используя limitToFirst :

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&limitToFirst=2&print=pretty'

Мы также можем выполнять запросы с ограничением количества элементов, используя orderBy="$value" . Если мы хотим создать таблицу лидеров с тремя участниками, набравшими наибольшее количество очков в соревнованиях по динозавровым видам спорта, мы можем сделать следующее:

curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&limitToLast=3&print=pretty'

Запросы диапазона

Использование startAt , endAt и equalTo позволяет выбирать произвольные начальные и конечные точки для запросов. Например, если мы хотим найти всех динозавров, рост которых составляет не менее трех метров, мы можем объединить orderBy и startAt :

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'

Мы можем использовать endAt , чтобы найти всех динозавров, чьи названия лексикографически предшествуют названию птеродактиля:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&endAt="pterodactyl"&print=pretty'

Мы можем объединить startAt и endAt , чтобы ограничить оба конца нашего запроса. Следующий пример находит всех динозавров, чье название начинается с буквы «б»:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="b"&endAt="b\uf8ff"&print=pretty'

Запросы с диапазоном значений также полезны, когда необходимо разбить данные на страницы.

Собираем всё воедино

Мы можем комбинировать все эти методы для создания сложных запросов. Например, вы можете захотеть найти названия всех динозавров, рост которых меньше или равен росту нашего любимого вида, стегозавра:

MY_FAV_DINO_HEIGHT=`curl "https://dinosaur-facts.firebaseio.com/dinosaurs/stegosaurus/height.json"`
curl "https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy=\"height\"&endAt=${MY_FAV_DINO_HEIGHT}&print=pretty"

Как упорядочены данные

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

orderBy

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

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

orderBy="$key"

При использовании параметра orderBy="$key" для сортировки данных, данные будут возвращены в порядке возрастания по ключу следующим образом. Имейте в виду, что ключи могут быть только строками.

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

orderBy="$value"

При использовании параметра orderBy="$value" для сортировки данных дочерние узлы будут упорядочены по их значению. Критерии сортировки такие же, как и для данных, упорядоченных по ключу дочернего узла, за исключением того, что используется значение узла, а не значение указанного ключа дочернего узла.

orderBy="$priority"

При использовании параметра orderBy="$priority" для сортировки данных порядок дочерних элементов определяется их приоритетом и ключом следующим образом. Имейте в виду, что значения приоритета могут быть только числами или строками.

  1. Дети, не имеющие приоритета (по умолчанию), стоят на первом месте.
  2. Следующими идут дети, приоритет которых указан номером. Их сортируют по приоритету в числовом порядке, от самых маленьких к самым старшим.
  3. Дети, для которых приоритетом является строка, располагаются в последнюю очередь. Они сортируются лексикографически по приоритету.
  4. Если у двух дочерних элементов одинаковый приоритет (включая отсутствие приоритета), они сортируются по ключу. Сначала идут числовые ключи (отсортированные по номеру), затем остальные ключи (отсортированные по лексикографическому принципу).

Для получения более подробной информации о приоритетах см. справочник API .

Потоковая передача данных через REST API

REST-конечные точки Firebase поддерживают протокол EventSource / Server-Sent Events , что упрощает потоковую передачу изменений в одно место в нашей базе данных Firebase.

Для начала работы со стримингом нам потребуется выполнить следующие действия:

  1. Установите заголовок Accept клиента в text/event-stream
  2. Учитывайте HTTP-перенаправления, в частности, HTTP-код состояния 307.
  3. Укажите параметр запроса auth , если для доступа к базе данных Firebase требуются разрешения на чтение.

В ответ сервер будет отправлять именованные события по мере изменения состояния данных по запрошенному URL-адресу. Структура этих сообщений соответствует протоколу EventSource:

event: event name
data: JSON encoded data payload

Сервер может отправлять следующие события:

помещать Данные в формате JSON будут представлять собой объект с двумя ключами: path и data.
Путь указывает на местоположение относительно URL-адреса запроса.
Клиент должен заменить все данные в этом месте своего кэша данными, указанными в сообщении.
пластырь Данные в формате JSON будут представлять собой объект с двумя ключами: path и data.
Путь указывает на местоположение относительно URL-адреса запроса.
Для каждого ключа в данных клиент должен заменить соответствующий ключ в своем кэше данными для этого ключа из сообщения.
поддерживать жизнь Данные по этому событию отсутствуют, никаких действий не требуется.
отмена Данные по этому событию отсутствуют.
Это событие будет отправлено, если Firebase Realtime Database Security Rules приведут к тому, что чтение из запрошенного места больше не будет разрешено.
auth_revoked Данные для этого события представляют собой строку, указывающую на то, что срок действия учетных данных истек.
Это событие будет отправлено, когда предоставленный параметр аутентификации перестанет быть действительным.

Ниже приведён пример набора событий, которые может отправить сервер:

// Set your entire cache to {"a": 1, "b": 2}
event: put
data: {"path": "/", "data": {"a": 1, "b": 2}}


// Put the new data in your cache under the key 'c', so that the complete cache now looks like:
// {"a": 1, "b": 2, "c": {"foo": true, "bar": false}}
event: put
data: {"path": "/c", "data": {"foo": true, "bar": false}}


// For each key in the data, update (or add) the corresponding key in your cache at path /c,
// for a final cache of: {"a": 1, "b": 2, "c": {"foo": 3, "bar": false, "baz": 4}}
event: patch
data: {"path": "/c", "data": {"foo": 3, "baz": 4}}

Если вы используете Go, обратите внимание на Firego — стороннюю обертку над REST и Streaming API Firebase.