Trabalhe com listas de dados na Web

Obtenha uma referência de banco de dados

Para ler ou gravar dados do banco de dados, você precisa de uma instância de firebase.database.Reference :

Web modular API

import { getDatabase } from "firebase/database";

const database = getDatabase();

Web namespaced API

var database = firebase.database();

Ler e escrever listas

Anexar a uma lista de dados

Use o método push() para anexar dados a uma lista em aplicativos multiusuário. O método push() gera uma chave exclusiva sempre que um novo filho é adicionado à referência especificada do Firebase. Ao usar essas chaves geradas automaticamente para cada novo elemento na lista, vários clientes podem adicionar filhos ao mesmo local ao mesmo tempo, sem conflitos de gravação. A chave exclusiva gerada por push() é baseada em um carimbo de data/hora, portanto os itens da lista são automaticamente ordenados cronologicamente.

Você pode usar a referência aos novos dados retornados pelo método push() para obter o valor da chave gerada automaticamente do filho ou definir dados para o filho. A propriedade .key de uma referência push() contém a chave gerada automaticamente.

Você pode usar essas chaves geradas automaticamente para simplificar o nivelamento de sua estrutura de dados. Para obter mais informações, consulte o exemplo de distribuição de dados.

Por exemplo, push() poderia ser usado para adicionar uma nova postagem a uma lista de postagens em uma aplicação social:

Web modular API

import { getDatabase, ref, push, set } from "firebase/database";

// Create a new post reference with an auto-generated id
const db = getDatabase();
const postListRef = ref(db, 'posts');
const newPostRef = push(postListRef);
set(newPostRef, {
    // ...
});

Web namespaced API

// Create a new post reference with an auto-generated id
var postListRef = firebase.database().ref('posts');
var newPostRef = postListRef.push();
newPostRef.set({
    // ...
});

Ouvir eventos infantis

Os eventos filhos são acionados em resposta a operações específicas que acontecem aos filhos de um nó a partir de uma operação, como um novo filho adicionado por meio do método push() ou um filho sendo atualizado por meio do método update() .

Evento Uso típico
child_added Recuperar listas de itens ou ouvir adições a uma lista de itens. Este evento é acionado uma vez para cada filho existente e novamente sempre que um novo filho é adicionado ao caminho especificado. O ouvinte recebe um instantâneo contendo os dados do novo filho.
child_changed Ouça as alterações nos itens de uma lista. Este evento é acionado sempre que um nó filho é modificado. Isto inclui quaisquer modificações nos descendentes do nó filho. O instantâneo passado para o ouvinte de evento contém os dados atualizados do filho.
child_removed Ouça os itens sendo removidos de uma lista. Este evento é acionado quando um filho imediato é removido. O instantâneo passado para o bloco de retorno de chamada contém os dados do filho removido.
child_moved Ouça as alterações na ordem dos itens em uma lista ordenada. Os eventos child_moved sempre seguem o evento child_changed que causou a alteração da ordem do item (com base no seu método de ordenação atual).

Cada um deles juntos pode ser útil para ouvir alterações em um nó específico em um banco de dados. Por exemplo, um aplicativo de blog social pode usar esses métodos juntos para monitorar a atividade nos comentários de uma postagem, conforme mostrado abaixo:

Web modular API

import { getDatabase, ref, onChildAdded, onChildChanged, onChildRemoved } from "firebase/database";

const db = getDatabase();
const commentsRef = ref(db, 'post-comments/' + postId);
onChildAdded(commentsRef, (data) => {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

onChildChanged(commentsRef, (data) => {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

onChildRemoved(commentsRef, (data) => {
  deleteComment(postElement, data.key);
});

Web namespaced API

var commentsRef = firebase.database().ref('post-comments/' + postId);
commentsRef.on('child_added', (data) => {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_changed', (data) => {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_removed', (data) => {
  deleteComment(postElement, data.key);
});

Ouça eventos de valor

Embora a escuta de eventos filhos seja a maneira recomendada de ler listas de dados, há situações em que é útil ouvir eventos de valor em uma referência de lista.

Anexar um observador value a uma lista de dados retornará a lista inteira de dados como um único instantâneo que você pode percorrer para acessar filhos individuais.

Mesmo quando há apenas uma correspondência para a consulta, o instantâneo ainda é uma lista; ele contém apenas um único item. Para acessar o item, você precisa percorrer o resultado:

Web modular API

import { getDatabase, ref, onValue } from "firebase/database";

const db = getDatabase();
const dbRef = ref(db, '/a/b/c');

onValue(dbRef, (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    const childKey = childSnapshot.key;
    const childData = childSnapshot.val();
    // ...
  });
}, {
  onlyOnce: true
});

Web namespaced API

ref.once('value', (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // ...
  });
});

Esse padrão pode ser útil quando você deseja buscar todos os filhos de uma lista em uma única operação, em vez de escutar eventos adicionais adicionados por filhos.

Classificando e filtrando dados

Você pode usar a classe Realtime Database Query para recuperar dados classificados por chave, por valor ou por valor de um filho. Você também pode filtrar o resultado classificado para um número específico de resultados ou um intervalo de chaves ou valores.

Classificar dados

Para recuperar dados classificados, comece especificando um dos métodos ordenados por para determinar como os resultados são ordenados:

Método Uso
orderByChild() Ordene os resultados pelo valor de uma chave filha especificada ou de um caminho filho aninhado.
orderByKey() Ordene os resultados por chaves filhas.
orderByValue() Ordene os resultados por valores filhos.

Você só pode usar um método de ordem por vez. Chamar um método ordenado várias vezes na mesma consulta gera um erro.

O exemplo a seguir demonstra como você pode recuperar uma lista das principais postagens de um usuário, classificadas pela contagem de estrelas:

Web modular API

import { getDatabase, ref, query, orderByChild } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const myUserId = auth.currentUser.uid;
const topUserPostsRef = query(ref(db, 'user-posts/' + myUserId), orderByChild('starCount'));

Web namespaced API

var myUserId = firebase.auth().currentUser.uid;
var topUserPostsRef = firebase.database().ref('user-posts/' + myUserId).orderByChild('starCount');

Isso define uma consulta que, quando combinada com um ouvinte filho, sincroniza o cliente com as postagens do usuário a partir do caminho no banco de dados com base em seu ID de usuário, ordenado pelo número de estrelas que cada postagem recebeu. Essa técnica de usar IDs como chaves de índice é chamada de data fan out, você pode ler mais sobre isso em Estruture seu banco de dados .

A chamada ao método orderByChild() especifica a chave filha pela qual ordenar os resultados. Nesse caso, as postagens são ordenadas pelo valor do respectivo filho "starCount" . As consultas também podem ser ordenadas por filhos aninhados, caso você tenha dados semelhantes a estes:

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

Nesse caso, podemos ordenar nossos elementos de lista por valores aninhados na chave metrics , especificando o caminho relativo para o filho aninhado em nossa chamada orderByChild() .

Web modular API

import { getDatabase, ref, query, orderByChild } from "firebase/database";

const db = getDatabase();
const mostViewedPosts = query(ref(db, 'posts'), orderByChild('metrics/views'));

Web namespaced API

var mostViewedPosts = firebase.database().ref('posts').orderByChild('metrics/views');

Para obter mais informações sobre como outros tipos de dados são ordenados, consulte Como os dados de consulta são ordenados .

Filtrando dados

Para filtrar dados, você pode combinar qualquer um dos métodos de limite ou intervalo com um método ordenado por ao construir uma consulta.

Método Uso
limitToFirst() Define o número máximo de itens a serem retornados do início da lista ordenada de resultados.
limitToLast() Define o número máximo de itens a serem retornados do final da lista ordenada de resultados.
startAt() Retorna itens maiores ou iguais à chave ou valor especificado, dependendo do método de ordenação escolhido.
startAfter() Retorna itens maiores que a chave ou valor especificado dependendo do método de ordenação escolhido.
endAt() Retorna itens menores ou iguais à chave ou valor especificado, dependendo do método de ordenação escolhido.
endBefore() Retorna itens menores que a chave ou valor especificado, dependendo do método de ordenação escolhido.
equalTo() Retorna itens iguais à chave ou valor especificado, dependendo do método de ordenação escolhido.

Ao contrário dos métodos ordenados, você pode combinar várias funções de limite ou intervalo. Por exemplo, você pode combinar os métodos startAt() e endAt() para limitar os resultados a um intervalo especificado de valores.

Limite o número de resultados

Você pode usar os métodos limitToFirst() e limitToLast() para definir um número máximo de filhos a serem sincronizados para um determinado evento. Por exemplo, se você usar limitToFirst() para definir um limite de 100, inicialmente receberá apenas até 100 eventos child_added . Se você tiver menos de 100 itens armazenados no banco de dados do Firebase, um evento child_added será acionado para cada item.

À medida que os itens mudam, você recebe eventos child_added para itens que entram na consulta e eventos child_removed para itens que saem dela, de modo que o número total permaneça em 100.

O exemplo a seguir demonstra como o aplicativo de blog de exemplo define uma consulta para recuperar uma lista das 100 postagens mais recentes de todos os usuários:

Web modular API

import { getDatabase, ref, query, limitToLast } from "firebase/database";

const db = getDatabase();
const recentPostsRef = query(ref(db, 'posts'), limitToLast(100));

Web namespaced API

var recentPostsRef = firebase.database().ref('posts').limitToLast(100);

Este exemplo define apenas uma consulta, para realmente sincronizar os dados ela precisa ter um listener anexado.

Filtrar por chave ou valor

Você pode usar startAt() , startAfter() , endAt() , endBefore() e equalTo() para escolher pontos iniciais, finais e de equivalência arbitrários para consultas. Isso pode ser útil para paginar dados ou encontrar itens com filhos que tenham um valor específico.

Como os dados da consulta são ordenados

Esta seção explica como os dados são classificados por cada um dos métodos ordenados na classe Query .

orderByChild

Ao usar orderByChild() , os dados que contêm a chave filha especificada são ordenados da seguinte forma:

  1. Os filhos com um valor null para a chave filha especificada vêm primeiro.
  2. Os filhos com um valor false para a chave filha especificada vêm em seguida. Se vários filhos tiverem um valor false , eles serão classificados lexicograficamente por chave.
  3. Os filhos com um valor true para a chave filha especificada vêm em seguida. Se vários filhos tiverem um valor true , eles serão classificados lexicograficamente por chave.
  4. Os filhos com valor numérico vêm em seguida, classificados em ordem crescente. Se vários filhos tiverem o mesmo valor numérico para o nó filho especificado, eles serão classificados por chave.
  5. As strings vêm depois dos números e são classificadas lexicograficamente em ordem crescente. Se vários filhos tiverem o mesmo valor para o nó filho especificado, eles serão ordenados lexicograficamente por chave.
  6. Os objetos vêm por último e são classificados lexicograficamente por chave em ordem crescente.

orderByKey

Ao usar orderByKey() para classificar seus dados, os dados são retornados em ordem crescente por chave.

  1. Os filhos com uma chave que pode ser analisada como um número inteiro de 32 bits vêm primeiro, classificados em ordem crescente.
  2. Os filhos com um valor de string como chave vêm em seguida, classificados lexicograficamente em ordem crescente.

orderByValue

Ao usar orderByValue() , os filhos são ordenados por seu valor. Os critérios de ordenação são os mesmos de orderByChild() , exceto que o valor do nó é usado em vez do valor de uma chave filha especificada.

Desanexar ouvintes

Os retornos de chamada são removidos chamando o método off() na referência do banco de dados do Firebase.

Você pode remover um único ouvinte passando-o como parâmetro para off() . Chamar off() no local sem argumentos remove todos os ouvintes naquele local.

Chamar off() em um ouvinte pai não remove automaticamente os ouvintes registrados em seus nós filhos; off() também deve ser chamado em qualquer ouvinte filho para remover o retorno de chamada.

Próximos passos