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

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

СТАВИТЬ Запишите или замените данные по определенному пути , например 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 сохраняется в базе данных, свойства объекта автоматически сопоставляются с дочерними местоположениями во вложенном виде. Если мы перейдем к вновь созданному узлу, мы увидим значение «Алан Тьюринг». Мы также можем сохранять данные непосредственно в дочернем местоположении:

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]'
    
    Если значение данных в указанном location по-прежнему равен 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. Используйте новую информацию, если вы решите повторить запрос. База данных реального времени не повторяет автоматически невыполненные условные запросы. Однако вы можете использовать новое значение и ETag для создания нового условного запроса с информацией, возвращаемой отказоустойчивым ответом.

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

  • Вы можете указать только одно значение ETag для каждого запроса if-match, а не несколько.
  • Хотя стандарт предполагает, что ETag возвращаются со всеми запросами, база данных реального времени возвращает 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 , и поддерживается всеми типами запросов. Аргументом может быть либо секрет нашего приложения 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 .
  • Запрос не поддерживает один из указанных параметров запроса.
  • Запрос смешивает параметры запроса с поверхностным запросом GET .
401 Неавторизованный

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

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

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

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

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