Salvando dados

Maneiras de salvar dados

COLOCAR Escreva ou substitua dados em um caminho definido , como fireblog/users/user1/<data>
CORREÇÃO Atualize algumas das chaves de um caminho definido sem substituir todos os dados.
PUBLICAR Adicione a uma lista de dados em nosso banco de dados Firebase. Cada vez que enviamos uma solicitação POST , o cliente Firebase gera uma chave exclusiva, como fireblog/users/<unique-id>/<data>
EXCLUIR Remova os dados da referência de banco de dados do Firebase especificada.

Escrevendo dados com PUT

A operação básica de gravação por meio da API REST é PUT . Para demonstrar o salvamento de dados, construiremos um aplicativo de blog com postagens e usuários. Todos os dados do nosso aplicativo serão armazenados no caminho `fireblog`, na URL do banco de dados Firebase `https://docs-examples.firebaseio.com/fireblog`.

Vamos começar salvando alguns dados do usuário em nosso banco de dados Firebase. Armazenaremos cada usuário com um nome de usuário exclusivo e também armazenaremos seu nome completo e data de nascimento. Como cada usuário terá um nome de usuário exclusivo, faz sentido usar PUT aqui em vez de POST , pois já temos a chave e não precisamos criar uma.

Usando PUT , podemos escrever uma string, número, booleano, array ou qualquer objeto JSON em nosso banco de dados Firebase. Neste caso, passaremos um objeto:

curl -X PUT -d '{
  "alanisawesome": {
    "name": "Alan Turing",
    "birthday": "June 23, 1912"
  }
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'

Quando um objeto JSON é salvo no banco de dados, as propriedades do objeto são automaticamente mapeadas para locais filho de forma aninhada. Se navegarmos até o nó recém-criado, veremos o valor “Alan Turing”. Também podemos salvar dados diretamente em um local filho:

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'

Os dois exemplos acima – escrever o valor ao mesmo tempo que um objeto e gravá-los separadamente em locais filhos – resultarão no salvamento dos mesmos dados em nosso banco de dados Firebase:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    }
  }
}

Uma solicitação bem-sucedida será indicada por um código de status HTTP 200 OK e a resposta conterá os dados que gravamos no banco de dados. O primeiro exemplo acionará apenas um evento em clientes que estão monitorando os dados, enquanto o segundo exemplo acionará dois. É importante observar que se os dados já existissem no caminho do usuário, a primeira abordagem os substituiria, mas o segundo método apenas modificaria o valor de cada nó filho separado, deixando os outros filhos inalterados. PUT é equivalente a set() em nosso SDK JavaScript.

Atualizando Dados com PATCH

Usando uma solicitação PATCH , podemos atualizar filhos específicos em um local sem substituir os dados existentes. Vamos adicionar o apelido de Turing aos seus dados de usuário com uma solicitação PATCH :

curl -X PATCH -d '{
  "nickname": "Alan The Machine"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

A solicitação acima irá escrever nickname em nosso objeto alanisawesome sem excluir o name ou birthday dos filhos. Observe que se tivéssemos emitido uma solicitação PUT aqui, name e birthday teriam sido excluídos, pois não foram incluídos na solicitação. Os dados em nosso banco de dados Firebase agora ficam assim:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    }
  }
}

Uma solicitação bem-sucedida será indicada por um código de status HTTP 200 OK e a resposta conterá os dados atualizados gravados no banco de dados.

O Firebase também oferece suporte a atualizações de vários caminhos. Isso significa que PATCH agora pode atualizar valores em vários locais do banco de dados Firebase ao mesmo tempo, um recurso poderoso que ajuda a desnormalizar seus dados . Usando atualizações de vários caminhos, podemos adicionar apelidos para Alan e Grace ao mesmo tempo:

curl -X PATCH -d '{
  "alanisawesome/nickname": "Alan The Machine",
  "gracehopper/nickname": "Amazing Grace"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Após esta atualização, Alan e Grace tiveram seus apelidos adicionados:

{
  "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"
    }
  }
}

Observe que tentar atualizar objetos escrevendo objetos com os caminhos incluídos resultará em um comportamento diferente. Vamos dar uma olhada no que acontece se tentarmos atualizar Grace e Alan desta forma:

curl -X PATCH -d '{
  "alanisawesome": {"nickname": "Alan The Machine"},
  "gracehopper": {"nickname": "Amazing Grace"}
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Isso resulta em um comportamento diferente, ou seja, sobrescrevendo todo o nó /fireblog/users :

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

Atualizando Dados com Solicitações Condicionais

Você pode usar solicitações condicionais, o REST equivalente às transações, para atualizar os dados de acordo com seu estado existente. Por exemplo, se você quiser aumentar um contador de votos positivos e garantir que a contagem reflita com precisão vários votos positivos simultâneos, use uma solicitação condicional para gravar o novo valor no contador. Em vez de duas gravações que alteram o contador para o mesmo número, uma das solicitações de gravação falha e você pode tentar novamente a solicitação com o novo valor.
  1. Para realizar uma solicitação condicional em um local, obtenha o identificador exclusivo dos dados atuais nesse local, ou a ETag. Se os dados mudarem nesse local, a ETag também mudará. Você pode solicitar uma ETag com qualquer método diferente de PATCH . O exemplo a seguir usa uma solicitação GET .
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    
    Chamar especificamente o ETag no cabeçalho retorna o ETag do local especificado na resposta 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. Inclua a ETag retornada em sua próxima solicitação PUT ou DELETE para atualizar dados que correspondam especificamente a esse valor de ETag. Seguindo nosso exemplo, para atualizar o contador para 11, ou 1 maior que o valor inicial buscado de 10, e falhar na solicitação se o valor não corresponder mais, use o seguinte código:
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    
    Se o valor dos dados no valor especificado location ainda for 10, o ETag na solicitação PUT corresponderá e a solicitação será bem-sucedida, gravando 11 no banco de dados.
    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
    
    Se o local não corresponder mais ao ETag, o que poderá ocorrer se outro usuário gravar um novo valor no banco de dados, a solicitação falhará sem gravar no local. A resposta de retorno inclui o novo valor e a 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. Use as novas informações se decidir tentar novamente a solicitação. O Realtime Database não tenta novamente solicitações condicionais que falharam automaticamente. No entanto, você pode usar o novo valor e a ETag para criar uma nova solicitação condicional com as informações retornadas pela resposta de falha.

Solicitações condicionais baseadas em REST implementam o padrão HTTP if-match . No entanto, eles diferem do padrão nas seguintes maneiras:

  • Você só pode fornecer um valor ETag para cada solicitação if-match, e não vários.
  • Embora o padrão sugira que as ETags sejam retornadas com todas as solicitações, o Realtime Database retorna apenas ETags com solicitações que incluem o cabeçalho X-Firebase-ETag . Isso reduz os custos de faturamento para solicitações padrão.

As solicitações condicionais também podem ser mais lentas que as solicitações REST típicas.

Salvando listas de dados

Para gerar uma chave exclusiva baseada em carimbo de data/hora para cada filho adicionado a uma referência de banco de dados Firebase, podemos enviar uma solicitação POST . Para o caminho de nossos users , fazia sentido definir nossas próprias chaves, já que cada usuário possui um nome de usuário exclusivo. Mas quando os usuários adicionam postagens de blog ao aplicativo, usaremos uma solicitação POST para gerar automaticamente uma chave para cada postagem do blog:

curl -X POST -d '{
  "author": "alanisawesome",
  "title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'

Nosso caminho posts agora possui os seguintes dados:

{
  "posts": {
    "-JSOpn9ZC54A4P4RoqVa": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

Observe que a chave -JSOpn9ZC54A4P4RoqVa foi gerada automaticamente para nós porque usamos uma solicitação POST . Uma solicitação bem-sucedida será indicada por um código de status HTTP 200 OK e a resposta conterá a chave dos novos dados que foram adicionados:

{"name":"-JSOpn9ZC54A4P4RoqVa"}

Removendo Dados

Para remover dados do banco de dados, podemos enviar uma solicitação DELETE com a URL do caminho do qual gostaríamos de excluir os dados. O seguinte excluiria Alan do caminho de nossos users :

curl -X DELETE \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Uma solicitação DELETE bem-sucedida será indicada por um código de status HTTP 200 OK com uma resposta contendo JSON null .

Parâmetros URI

A API REST aceita os seguintes parâmetros de URI ao gravar dados no banco de dados:

autenticação

O parâmetro de solicitação auth permite acesso a dados protegidos pelas regras de segurança do Firebase Realtime Database e é compatível com todos os tipos de solicitação. O argumento pode ser o segredo do nosso aplicativo Firebase ou um token de autenticação, que abordaremos na seção de autorização do usuário . No exemplo a seguir, enviamos uma solicitação POST com um parâmetro auth , onde CREDENTIAL é o segredo do nosso aplicativo Firebase ou um token de autenticação:

curl -X POST -d '{"Authenticated POST request"}' \
  'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

imprimir

O parâmetro print nos permite especificar o formato de nossa resposta do banco de dados. Adicionar print=pretty à nossa solicitação retornará os dados em um formato legível por humanos. print=pretty é suportado por solicitações GET , PUT , POST , PATCH e DELETE .

Para suprimir a saída do servidor ao gravar dados, podemos adicionar print=silent à nossa solicitação. A resposta resultante estará vazia e indicada por um código de status HTTP 204 No Content se a solicitação for bem-sucedida. O print=silent é suportado pelas solicitações GET , PUT , POST e PATCH .

Escrevendo Valores do Servidor

Os valores do servidor podem ser gravados em um local usando um valor de espaço reservado, que é um objeto com uma única chave ".sv" . O valor dessa chave é o tipo de valor de servidor que desejamos definir. Por exemplo, para definir um carimbo de data/hora quando um usuário é criado, poderíamos fazer o seguinte:

curl -X PUT -d '{".sv": "timestamp"}' \
  'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'

"timestamp" é o único valor de servidor suportado e é o tempo desde a época do UNIX em milissegundos.

Melhorando o desempenho de gravação

Se estivermos gravando grandes quantidades de dados no banco de dados, podemos usar o parâmetro print=silent para melhorar nosso desempenho de gravação e diminuir o uso de largura de banda. No comportamento normal de gravação, o servidor responde com os dados JSON que foram gravados. Quando print=silent é especificado, o servidor fecha imediatamente a conexão assim que os dados são recebidos, reduzindo o uso da largura de banda.

Nos casos em que fazemos muitas solicitações ao banco de dados, podemos reutilizar a conexão HTTPS enviando uma solicitação Keep-Alive no cabeçalho HTTP.

Condições de erro

A API REST retornará códigos de erro nestas circunstâncias:

Códigos de status HTTP
400 Solicitação incorreta

Uma das seguintes condições de erro:

  • Não é possível analisar dados PUT ou POST .
  • Dados PUT ou POST ausentes.
  • A solicitação tenta PUT ou POST dados que são muito grandes.
  • A chamada da API REST contém nomes filho inválidos como parte do caminho.
  • O caminho de chamada da API REST é muito longo.
  • A solicitação contém um valor de servidor não reconhecido.
  • O índice da consulta não está definido nas regras de segurança do Firebase Realtime Database .
  • A solicitação não suporta um dos parâmetros de consulta especificados.
  • A solicitação mistura parâmetros de consulta com uma solicitação GET superficial.
401 não autorizado

Uma das seguintes condições de erro:

404 não encontrado O banco de dados Firebase especificado não foi encontrado.
500 Erro interno do servidor O servidor retornou um erro. Consulte a mensagem de erro para obter mais detalhes.
503 serviço indisponível O Firebase Realtime Database especificado está temporariamente indisponível, o que significa que a solicitação não foi tentada.

Protegendo Dados

O Firebase possui uma linguagem de segurança que nos permite definir quais usuários têm acesso de leitura e gravação aos diferentes nós de nossos dados. Você pode ler mais sobre isso em Regras de segurança do Realtime Database .

Agora que cobrimos o salvamento de dados, podemos aprender como recuperar nossos dados do banco de dados Firebase por meio da API REST na próxima seção.