Способы сохранения данных | |
---|---|
ПОМЕЩАТЬ | Запишите или замените данные по указанному пути , например fireblog/users/user1/<data> |
ПЛАСТЫРЬ | Обновить некоторые ключи для определенного пути без замены всех данных. |
ПОЧТА | Добавляет данные в список нашей базы данных Firebase. Каждый раз, когда мы отправляем POST запрос, клиент Firebase генерирует уникальный ключ, например, fireblog/users/<unique-id>/<data> |
УДАЛИТЬ | Удалить данные из указанной ссылки базы данных Firebase. |
Запись данных с помощью PUT
Базовая операция записи через REST API — PUT
. Чтобы продемонстрировать сохранение данных, мы создадим приложение для блога с записями и пользователями. Все данные нашего приложения будут храниться по пути `fireblog`, по URL-адресу базы данных Firebase `https://docs-examples.firebaseio.com/fireblog`.
Начнём с сохранения данных пользователей в базе данных Firebase. Мы будем хранить каждого пользователя под уникальным именем, а также его полное имя и дату рождения. Поскольку у каждого пользователя будет уникальное имя, имеет смысл использовать PUT
вместо POST
поскольку у нас уже есть ключ, и нам не нужно его создавать.
Используя PUT
, мы можем записать строку, число, логическое значение, массив или любой JSON-объект в базу данных Firebase. В данном случае мы передадим ей объект:
curl -X PUT -d '{ "alanisawesome": { "name": "Alan Turing", "birthday": "June 23, 1912" } }' 'https://docs-examples.firebaseio.com/fireblog/users.json'
При сохранении JSON-объекта в базе данных свойства объекта автоматически сопоставляются с дочерними расположениями во вложенном порядке. Если перейти к только что созданному узлу, мы увидим значение «Alan Turing». Мы также можем сохранить данные непосредственно в дочернем расположении:
curl -X PUT -d '"Alan Turing"' \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'
Приведенные выше два примера — запись значения одновременно с объектом и запись их по отдельности в дочерние расположения — приведут к сохранению одних и тех же данных в нашей базе данных Firebase:
{ "users": { "alanisawesome": { "date_of_birth": "June 23, 1912", "full_name": "Alan Turing" } } }
Успешный запрос будет отмечен кодом статуса HTTP 200 OK
, а ответ будет содержать данные, записанные нами в базу данных. Первый пример вызовет только одно событие у клиентов, отслеживающих данные, тогда как второй пример — два. Важно отметить, что если данные уже существовали в пути пользователя, первый подход перезапишет их, а второй метод изменит только значение каждого отдельного дочернего узла, оставив остальные дочерние узлы без изменений. PUT
эквивалентен set()
в нашем JavaScript SDK.
Обновление данных с помощью PATCH
Используя PATCH
запрос, мы можем обновить данные о конкретных дочерних элементах в указанном месте, не перезаписывая существующие данные. Добавим псевдоним Тьюринга к его пользовательским данным с помощью PATCH
запроса:
curl -X PATCH -d '{ "nickname": "Alan The Machine" }' \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'
Запрос выше запишет nickname
в наш объект alanisawesome
, не удаляя name
и birthday
детей. Обратите внимание: если бы мы вместо этого выполнили PUT
запрос, name
и birthday
были бы удалены, поскольку они не были включены в запрос. Данные в нашей базе данных Firebase теперь выглядят следующим образом:
{ "users": { "alanisawesome": { "date_of_birth": "June 23, 1912", "full_name": "Alan Turing", "nickname": "Alan The Machine" } } }
Успешный запрос будет подтвержден кодом статуса HTTP 200 OK
, а ответ будет содержать обновленные данные, записанные в базу данных.
Firebase также поддерживает многопутевые обновления. Это означает, что PATCH
теперь может обновлять значения в нескольких местах базы данных Firebase одновременно — мощная функция, которая позволяет денормализовать данные . Используя многопутевые обновления, мы можем одновременно добавлять псевдонимы как для Алана, так и для Грейс:
curl -X PATCH -d '{ "alanisawesome/nickname": "Alan The Machine", "gracehopper/nickname": "Amazing Grace" }' \ 'https://docs-examples.firebaseio.com/fireblog/users.json'
После этого обновления у Алана и Грейс были добавлены прозвища:
{ "users": { "alanisawesome": { "date_of_birth": "June 23, 1912", "full_name": "Alan Turing", "nickname": "Alan The Machine" }, "gracehop": { "date_of_birth": "December 9, 1906", "full_name": "Grace Hopper", "nickname": "Amazing Grace" } } }
Обратите внимание, что попытка обновить объекты путём записи объектов с указанием путей приведёт к иному результату. Давайте посмотрим, что произойдёт, если мы попытаемся обновить Грейс и Алана следующим образом:
curl -X PATCH -d '{ "alanisawesome": {"nickname": "Alan The Machine"}, "gracehopper": {"nickname": "Amazing Grace"} }' \ 'https://docs-examples.firebaseio.com/fireblog/users.json'
Это приводит к разному поведению, а именно к перезаписи всего узла /fireblog/users
:
{ "users": { "alanisawesome": { "nickname": "Alan The Machine" }, "gracehop": { "nickname": "Amazing Grace" } } }
Обновление данных с помощью условных запросов
Вы можете использовать условные запросы, REST-аналог транзакций, для обновления данных в соответствии с их текущим состоянием. Например, если вы хотите увеличить счётчик голосов «за» и убедиться, что он точно отражает несколько одновременных голосов «за», используйте условный запрос для записи нового значения в счётчик. Вместо двух операций записи, изменяющих значение счётчика на одно и то же значение, один из запросов на запись завершится ошибкой, и вы сможете повторить запрос с новым значением.- Чтобы выполнить условный запрос к определённому местоположению, получите уникальный идентификатор текущих данных в этом месте, или ETag. При изменении данных в этом месте изменится и ETag. Вы можете запросить ETag любым методом, кроме
PATCH
. В следующем примере используетсяGET
запрос. В частности, вызов ETag в заголовке возвращает ETag указанного местоположения в HTTP-ответе.curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
HTTP/1.1 200 OK Content-Length: 6 Content-Type: application/json; charset=utf-8 Access-Control-Allow-Origin: * ETag: [ETAG_VALUE] Cache-Control: no-cache 10 // Current value of the data at the specified location
- Включите возвращаемый ETag в следующий запрос
PUT
илиDELETE
, чтобы обновить данные, которые соответствуют этому значению ETag. Следуя нашему примеру, чтобы обновить счётчик до 11, или на 1 больше первоначально полученного значения 10, и отменить запрос, если значение больше не соответствует, используйте следующий код: Если значение данных в указанном месте по-прежнему равно 10, ETag в запросеcurl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
PUT
совпадает, и запрос выполняется успешно, записывая 11 в базу данных. Если местоположение больше не соответствует ETag, что может произойти, если другой пользователь записал новое значение в базу данных, запрос завершается ошибкой без записи в местоположение. Возвращаемый ответ включает новое значение и ETag.HTTP/1.1 200 OK Content-Length: 6 Content-Type: application/json; charset=utf-8 Access-Control-Allow-Origin: * Cache-Control: no-cache 11 // New value of the data at the specified location, written by the conditional request
HTTP/1.1 412 Precondition Failed Content-Length: 6 Content-Type: application/json; charset=utf-8 Access-Control-Allow-Origin: * ETag: [ETAG_VALUE] Cache-Control: no-cache 12 // New value of the data at the specified location
- Используйте новую информацию, если решите повторить запрос. Realtime Database не выполняет автоматически повторные условные запросы, которые завершились неудачей. Однако вы можете использовать новое значение и ETag для создания нового условного запроса с информацией, возвращаемой в ответе об ошибке.
Условные запросы на основе REST реализуют стандарт HTTP if-match . Однако они отличаются от стандарта следующим:
- Для каждого запроса if-match можно указать только одно значение ETag, а не несколько.
- Хотя стандарт предполагает возврат ETag со всеми запросами, Realtime Database возвращает ETag только с запросами, содержащими заголовок
X-Firebase-ETag
. Это снижает расходы на оплату стандартных запросов.
Условные запросы также могут быть медленнее обычных запросов REST.
Сохранение списков данных
Чтобы сгенерировать уникальный ключ с временной меткой для каждого дочернего элемента, добавленного в ссылку базы данных Firebase, мы можем отправить POST
запрос. Для пути наших users
имело смысл определить собственные ключи, поскольку у каждого пользователя уникальное имя. Но когда пользователи добавляют записи блога в приложение, мы будем использовать POST
запрос для автоматической генерации ключа для каждой записи блога:
curl -X POST -d '{ "author": "alanisawesome", "title": "The Turing Machine" }' 'https://docs-examples.firebaseio.com/fireblog/posts.json'
Теперь наш путь posts
содержит следующие данные:
{ "posts": { "-JSOpn9ZC54A4P4RoqVa": { "author": "alanisawesome", "title": "The Turing Machine" } } }
Обратите внимание, что ключ -JSOpn9ZC54A4P4RoqVa
был автоматически сгенерирован, поскольку мы использовали POST
запрос. Успешное выполнение запроса будет подтверждено кодом статуса HTTP 200 OK
, а ответ будет содержать ключ новых добавленных данных:
{"name":"-JSOpn9ZC54A4P4RoqVa"}
Удаление данных
Чтобы удалить данные из базы данных, мы можем отправить запрос DELETE
с URL-адресом пути, из которого мы хотим удалить данные. Следующий код удалит Алана из пути users
:
curl -X DELETE \ 'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'
Успешный запрос DELETE
будет обозначен кодом статуса HTTP 200 OK
с ответом, содержащим JSON null
.
Параметры URI
REST API принимает следующие параметры URI при записи данных в базу данных:
аутентификация
Параметр запроса auth
позволяет получить доступ к данным, защищённым Firebase Realtime Database Security Rules , и поддерживается всеми типами запросов. Аргументом может быть как секрет приложения Firebase, так и токен аутентификации, о чём мы поговорим в разделе об авторизации пользователя . В следующем примере мы отправляем POST
запрос с параметром auth
, где CREDENTIAL
— это либо секрет приложения Firebase, либо токен аутентификации:
curl -X POST -d '{"Authenticated POST request"}' \ 'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'
печать
Параметр print
позволяет задать формат ответа из базы данных. Добавление print=pretty
к нашему запросу вернет данные в удобном для восприятия формате. print=pretty
поддерживается запросами GET
, PUT
, POST
, PATCH
и DELETE
.
Чтобы подавить вывод данных с сервера, можно добавить к запросу print=silent
. Полученный ответ будет пустым и будет отмечен кодом статуса HTTP 204 No Content
в случае успешного выполнения запроса. Параметр print=silent
поддерживается запросами GET
, PUT
, POST
и PATCH
.
Запись значений сервера
Значения сервера можно записать в определённое место, используя значение-заполнитель, представляющее собой объект с одним ключом ".sv"
. Значение этого ключа — это тип значения сервера, который мы хотим установить. Например, чтобы установить временную метку при создании пользователя, можно сделать следующее:
curl -X PUT -d '{".sv": "timestamp"}' \ 'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'
"timestamp"
— единственное поддерживаемое сервером значение, представляющее собой время с начала эпохи UNIX в миллисекундах.
Повышение производительности записи
При записи больших объёмов данных в базу данных можно использовать параметр print=silent
для повышения производительности записи и снижения нагрузки на полосу пропускания. При обычной записи сервер отвечает записанными JSON-данными. При указании параметра print=silent
сервер немедленно закрывает соединение после получения данных, что снижает нагрузку на полосу пропускания.
В случаях, когда мы делаем много запросов к базе данных, мы можем повторно использовать HTTPS-соединение, отправив запрос Keep-Alive
в заголовке HTTP.
Ошибочные состояния
REST API будет возвращать коды ошибок при следующих обстоятельствах:
Коды состояния HTTP | |
---|---|
400 Неверный запрос | Одно из следующих состояний ошибки:
|
401 Неавторизованный | Одно из следующих состояний ошибки:
|
404 Не найдено | Указанная база данных Firebase не найдена. |
500 Внутренняя ошибка сервера | Сервер вернул ошибку. Подробности см. в сообщении об ошибке. |
503 Служба недоступна | Указанная база данных Firebase Realtime временно недоступна, что означает, что запрос не был выполнен. |
Защита данных
В Firebase есть язык безопасности, позволяющий определять, какие пользователи имеют доступ на чтение и запись к различным узлам наших данных. Подробнее об этом можно узнать в разделе Realtime Database Security Rules .
Теперь, когда мы рассмотрели сохранение данных, в следующем разделе мы можем узнать, как извлечь наши данные из базы данных Firebase через REST API.