Сохранение данных

Способы сохранения данных

ПОМЕЩАТЬ Запишите или замените данные по указанному пути , например 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, для обновления данных в соответствии с их текущим состоянием. Например, если вы хотите увеличить счетчик голосов «за» и хотите убедиться, что счетчик точно отражает несколько одновременных голосов «за», используйте условный запрос для записи нового значения в счетчик. Вместо двух записей, которые изменяют счетчик на одно и то же число, один из запросов записи завершается неудачей, и вы можете повторить запрос с новым значением.
  1. Чтобы выполнить условный запрос в определенном месте, получите уникальный идентификатор текущих данных в этом месте или ETag. Если данные в этом месте изменяются, ETag тоже меняется. Вы можете запросить ETag любым методом, кроме PATCH . В следующем примере используется запрос GET .
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    Конкретный вызов ETag в заголовке возвращает ETag указанного местоположения в HTTP-ответе.
    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
  2. Включите возвращенный ETag в ваш следующий запрос PUT или DELETE для обновления данных, которые конкретно соответствуют этому значению ETag. Следуя нашему примеру, чтобы обновить счетчик до 11 или на 1 больше первоначального извлеченного значения 10 и завершить запрос неудачей, если значение больше не соответствует, используйте следующий код:
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    Если значение данных в указанном месте по-прежнему равно 10, ETag в запросе PUT совпадает, и запрос выполняется успешно, записывая 11 в базу данных.
    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
    Если местоположение больше не соответствует ETag, что может произойти, если другой пользователь записал новое значение в базу данных, запрос завершается неудачей без записи в местоположение. Возвращаемый ответ включает новое значение и ETag.
    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
  3. Используйте новую информацию, если вы решите повторить запрос. Realtime Database не повторяет автоматически условные запросы, которые не удалось выполнить. Однако вы можете использовать новое значение и ETag для создания нового условного запроса с информацией, возвращенной ответом о неудаче.

Условные запросы на основе REST реализуют стандарт HTTP if-match . Однако они отличаются от стандарта следующим:

  • Для каждого запроса if-match можно указать только одно значение ETag, а не несколько.
  • В то время как стандарт предполагает, что ETags должны возвращаться со всеми запросами, Realtime Database возвращает ETags только с запросами, включающими заголовок 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 Неверный запрос

Одно из следующих состояний ошибки:

  • Невозможно проанализировать данные PUT или POST .
  • Отсутствуют данные PUT или POST .
  • Запрос пытается PUT или POST слишком большие данные.
  • Вызов REST API содержит недопустимые имена дочерних элементов как часть пути.
  • Путь вызова REST API слишком длинный.
  • Запрос содержит нераспознанное серверное значение.
  • Индекс для запроса не определен в Firebase Realtime Database Security Rules .
  • Запрос не поддерживает один из указанных параметров запроса.
  • Запрос смешивает параметры запроса с поверхностным GET запросом.
401 Несанкционированный

Одно из следующих состояний ошибки:

  • Срок действия токена аутентификации истек.
  • Токен аутентификации, использованный в запросе, недействителен.
  • Аутентификация с помощью access_token не удалась.
  • Запрос нарушает Firebase Realtime Database Security Rules .
404 Не найдено Указанная база данных Firebase не найдена.
500 Внутренняя ошибка сервера Сервер вернул ошибку. Подробности смотрите в сообщении об ошибке.
503 Служба недоступна Указанная база данных Firebase Realtime временно недоступна, что означает, что запрос не был выполнен.

Защита данных

Firebase имеет язык безопасности, который позволяет нам определять, какие пользователи имеют доступ на чтение и запись к различным узлам наших данных. Вы можете прочитать больше об этом в Realtime Database Security Rules .

Теперь, когда мы рассмотрели сохранение данных, в следующем разделе мы можем узнать, как извлечь наши данные из базы данных Firebase через REST API.