Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Salvando dados

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Maneiras de salvar dados

COLOCAR Gravar ou substituir dados em um caminho definido , como fireblog/users/user1/<data>
CORREÇÃO Atualize algumas das chaves para um caminho definido sem substituir todos os dados.
PUBLICAR Adicione a uma lista de dados em nosso banco de dados Firebase. Sempre 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 de gravação básica por meio da API REST é PUT . Para demonstrar como salvar dados, criaremos um aplicativo de blog com postagens e usuários. Todos os dados do nosso aplicativo serão armazenados no caminho de `fireblog`, na URL do banco de dados do 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 por 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, number, boolean, 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 mapeadas automaticamente para locais filho de forma aninhada. Se navegarmos para 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 — gravar 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 nos clientes que estão observando 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 escreverá um nickname para nosso objeto alanisawesome sem excluir o name ou o birthday dos filhos. Observe que, se tivéssemos emitido uma solicitação PUT aqui, o name e a data de birthday teriam sido excluídos, pois não foram incluídos na solicitação. Os dados em nosso banco de dados Firebase agora são 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 o PATCH agora pode atualizar valores em vários locais em seu banco de dados Firebase ao mesmo tempo, um recurso poderoso que ajuda você a desnormalizar seus dados . Usando atualizações de vários caminhos, podemos adicionar apelidos a 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, tanto Alan quanto 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 equivalente REST a transações, para atualizar dados de acordo com seu estado existente. Por exemplo, se você deseja aumentar um contador de votos positivos e deseja certificar-se de 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 forem alterados nesse local, a ETag também será alterada. 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'
    
    especificamente a ETag no cabeçalho retorna a 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 for especificado location ainda é 10, a ETag na solicitação PUT corresponde e a solicitação é 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 à ETag, o que pode 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 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 repetir a solicitação. O Realtime Database não repete automaticamente as solicitações condicionais que falharam. No entanto, você pode usar o novo valor e ETag para criar uma nova solicitação condicional com as informações retornadas pela resposta com falha.

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

  • Você só pode fornecer um valor de ETag para cada solicitação if-match, não várias.
  • Embora o padrão sugira que 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 do 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 do Firebase, podemos enviar uma solicitação POST . Para o caminho de nossos users , fazia sentido definir nossas próprias chaves, pois 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 de blog:

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

Nosso caminho de posts agora tem 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 desejamos excluir os dados. O seguinte excluiria Alan do nosso caminho de 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 de 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 de auth permite o acesso a dados protegidos pelas regras do Firebase Realtime Database e é compatível com todos os tipos de solicitação. O argumento pode ser nosso segredo do 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 de auth , em que CREDENTIAL é o segredo do 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 será vazia e indicada por um código de status HTTP 204 No Content se a solicitação for bem-sucedida. O print=silent é suportado por 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 do servidor que desejamos definir. Por exemplo, para definir um timestamp quando um usuário é criado, podemos 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 da largura de banda. No comportamento de gravação normal, 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 estamos fazendo 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 Inválida

Uma das seguintes condições de erro:

  • Não foi possível analisar os dados PUT ou POST .
  • Dados PUT ou POST ausentes.
  • A solicitação tenta POST PUT muito grandes.
  • A chamada da API REST contém nomes filhos 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 do Firebase Realtime Database .
  • A solicitação não oferece suporte a 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:

  • O token de autenticação expirou.
  • O token de autenticação usado na solicitação é inválido.
  • Falha na autenticação com um access_token.
  • A solicitação viola suas regras do Firebase Realtime Database.
404 Não Encontrado O banco de dados do 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 a diferentes nós de nossos dados. Você pode ler mais sobre isso em Regras do Realtime Database .

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