É possível contar quantos itens uma coleção possui usando o novo banco de dados Firebase, o Cloud Firestore?
Se sim, como faço isso?
firebase
google-cloud-firestore
Guilherme Torres Castro
fonte
fonte
Respostas:
Atualização (abril de 2019) - FieldValue.increment (consulte solução de coleção grande)
Como em muitas perguntas, a resposta é - depende .
Você deve ter muito cuidado ao lidar com grandes quantidades de dados no front-end. Além de tornar seu front end lento, o Firestore também cobra US $ 0,60 por milhão de leituras que você faz.
Pequena coleção (menos de 100 documentos)
Use com cuidado - a experiência do usuário do front-end pode sofrer um impacto
Lidar com isso no front-end deve ser bom, desde que você não faça muita lógica com essa matriz retornada.
Coleção média (100 a 1000 documentos)
Use com cuidado - as chamadas de leitura do Firestore podem custar muito
Lidar com isso no front end não é viável, pois tem muito potencial para desacelerar o sistema dos usuários. Devemos lidar com esse lado do servidor lógico e retornar apenas o tamanho.
A desvantagem desse método é que você ainda está invocando leituras do firestore (iguais ao tamanho da sua coleção), que a longo prazo podem acabar custando mais do que o esperado.
Função de nuvem:
A parte dianteira:
Grande coleção (mais de 1000 documentos)
Solução mais escalável
A partir de abril de 2019, o Firestore agora permite incrementar contadores, completamente atomicamente e sem ler os dados antes . Isso garante que temos valores corretos de contador, mesmo quando atualizamos de várias fontes simultaneamente (resolvidas anteriormente usando transações), além de reduzir o número de leituras de banco de dados que realizamos.
Ao ouvir qualquer documento excluído ou criado, podemos adicionar ou remover de um campo de contagem localizado no banco de dados.
Consulte os documentos do firestore - Contadores distribuídos ou dê uma olhada na agregação de dados por Jeff Delaney. Seus guias são realmente fantásticos para quem usa o AngularFire, mas suas lições devem passar para outras estruturas também.
Função de nuvem:
Agora, no front-end, você pode consultar este campo numberOfDocs para obter o tamanho da coleção.
fonte
firestore.runTransaction { ... }
bloco. Isso corrige problemas de concorrência com o acessonumberOfDocs
.A maneira mais simples de fazer isso é ler o tamanho de um "querySnapshot".
Você também pode ler o comprimento da matriz de documentos em "querySnapshot".
Ou se um "querySnapshot" estiver vazio lendo o valor vazio, que retornará um valor booleano.
fonte
db.collection.count()
. Pensando em largá-los apenas por isso #Até onde eu sei, não existe uma solução incorporada para isso e só é possível no nó sdk no momento. Se você tem um
você pode usar
para definir qual campo você deseja selecionar. Se você selecionar vazio (), obterá apenas uma série de referências a documentos.
exemplo:
db.collection('someCollection').select().get().then( (snapshot) => console.log(snapshot.docs.length) );
Esta solução é apenas uma otimização para o pior caso de baixar todos os documentos e não é escalável em grandes coleções!
Veja também:
Como obter uma contagem do número de documentos em uma coleção com o Cloud Firestore
fonte
select(['_id'])
é mais rápido do queselect()
Tenha cuidado ao contar o número de documentos para grandes coleções . É um pouco complexo com o banco de dados do firestore se você deseja ter um contador pré-calculado para cada coleção.
Código como este não funciona neste caso:
O motivo é que cada acionador do firestore na nuvem precisa ser idempotente, como a documentação do firestore diz: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Solução
Portanto, para impedir várias execuções do seu código, você precisa gerenciar com eventos e transações. Esta é minha maneira particular de lidar com grandes contadores de coleções:
Casos de uso aqui:
Como você pode ver, a chave para impedir a execução múltipla é a propriedade chamada eventId no objeto de contexto. Se a função tiver sido manipulada várias vezes para o mesmo evento, o ID do evento será o mesmo em todos os casos. Infelizmente, você deve ter a coleção "events" em seu banco de dados.
fonte
context.eventId
sempre será o mesmo em várias invocações do mesmo gatilho? Nos meus testes, parece ser consistente, mas não consigo encontrar nenhuma documentação "oficial" afirmando isso.Em 2020, isso ainda não está disponível no Firebase SDK, no entanto, está disponível no Firebase Extensions (Beta), no entanto, é bastante complexo configurar e usar ...
Uma abordagem razoável
Ajudantes ... (criar / excluir parece redundante, mas é mais barato que o onUpdate)
Ganchos de Firestore exportados
Em ação
A coleção raiz do edifício e todas as sub-coleções serão rastreadas.
Aqui sob o
/counters/
caminho da raizAgora a contagem de coleções será atualizada automaticamente e, eventualmente! Se você precisar de uma contagem, basta usar o caminho da coleção e prefixá-lo
counters
.fonte
Concordo com @ Matthew, vai custar muito se você realizar essa consulta.
[CONSELHOS PARA DESENVOLVEDORES ANTES DE INICIAR SEUS PROJETOS]
Como previmos essa situação no início, podemos realmente fazer uma coleção, ou seja, contadores com um documento para armazenar todos os contadores em um campo com o tipo
number
.Por exemplo:
Para cada operação CRUD na coleção, atualize o documento do contador:
Da próxima vez, quando você quiser obter o número de coleção, basta consultar / apontar para o campo do documento. [1 operação de leitura]
Além disso, você pode armazenar o nome das coleções em uma matriz, mas isso será complicado, a condição da matriz na firebase é mostrada abaixo:
Portanto, se você não excluir a coleção, poderá usar a matriz para armazenar a lista de nomes de coleções em vez de consultar toda a coleção todas as vezes.
Espero que ajude!
fonte
Não, não há suporte interno para consultas de agregação no momento. No entanto, existem algumas coisas que você poderia fazer.
O primeiro está documentado aqui . Você pode usar transações ou funções da nuvem para manter as informações agregadas:
Este exemplo mostra como usar uma função para acompanhar o número de classificações em uma subcoleção, bem como a classificação média.
A solução mencionada pela jbb também é útil se você quiser contar documentos com pouca frequência. Certifique-se de usar a
select()
instrução para evitar o download de todos os documentos (é muita largura de banda quando você precisa apenas de uma contagem).select()
está disponível apenas nos SDKs do servidor por enquanto, para que a solução não funcione em um aplicativo móvel.fonte
Não há opção direta disponível. Você não pode fazer
db.collection("CollectionName").count()
. Abaixo estão as duas maneiras pelas quais você pode encontrar a contagem do número de documentos em uma coleção.1: - Obtenha todos os documentos da coleção e obtenha seu tamanho (não é a melhor solução)
Ao usar o código acima, as leituras de seu documento serão iguais ao tamanho dos documentos em uma coleção e é por isso que é necessário evitar o uso da solução acima.
2: - Crie um documento separado em sua coleção que armazene a contagem do número de documentos na coleção. (Melhor solução)
Acima, criamos um documento com contagem de nomes para armazenar todas as informações de contagem. Você pode atualizar o documento de contagem da seguinte maneira: -
preço wrt (leitura de documento = 1) e recuperação rápida de dados, a solução acima é boa.
fonte
Incremente um contador usando admin.firestore.FieldValue.increment :
Neste exemplo, incrementamos um
instanceCount
campo no projeto cada vez que um documento é adicionado àinstances
sub-coleção. Se o campo ainda não existir, ele será criado e incrementado para 1.A incrementação é transacional internamente, mas você deve usar um contador distribuído se precisar incrementar com mais frequência do que a cada 1 segundo.
Geralmente, é preferível implementar
onCreate
e, emonDelete
vez deonWrite
solicitaronWrite
atualizações, o que significa que você está gastando mais dinheiro em invocações de funções desnecessárias (se você atualizar os documentos em sua coleção).fonte
Uma solução alternativa é:
escreva um contador em um documento da base de firmas, que você incrementa em uma transação toda vez que cria uma nova entrada
Você armazena a contagem em um campo da sua nova entrada (ou seja: posição: 4).
Em seguida, você cria um índice nesse campo (posição DESC).
Você pode fazer um salto + limite com uma consulta.Where ("position", "<" x) .OrderBy ("position", DESC)
Espero que isto ajude!
fonte
Criei uma função universal usando todas essas idéias para lidar com todas as situações de contador (exceto consultas).
Isso lida com eventos, incrementos e transações. A vantagem disso é que, se você não tiver certeza da precisão de um documento (provavelmente ainda em beta), poderá excluir o contador para que ele os adicione automaticamente no próximo gatilho. Sim, isso custa, portanto, não o exclua.
O mesmo tipo de coisa para obter a contagem:
Além disso, convém criar um trabalho cron (função agendada) para remover eventos antigos e economizar dinheiro no armazenamento do banco de dados. Você precisa de pelo menos um plano de incêndio, e pode haver mais configurações. Você pode executá-lo todos os domingos às 23h, por exemplo. https://firebase.google.com/docs/functions/schedule-functions
Isso não foi testado , mas deve funcionar com alguns ajustes:
E por último, não se esqueça de proteger as coleções no firestore.rules :
Atualização: consultas
Adicionando à minha outra resposta, se você deseja automatizar as contagens de consultas, também pode usar este código modificado na sua função de nuvem:
O qual atualizará automaticamente o postsCount no userDocument. Você pode facilmente adicionar outro a muitas contagens dessa maneira. Isso fornece idéias de como você pode automatizar as coisas. Também lhe dei outra maneira de excluir os eventos. Você precisa ler cada data para excluí-la, para que não seja realmente necessário excluí-las mais tarde, apenas torna a função mais lenta.
fonte
Levei um tempo para que isso funcionasse com base em algumas das respostas acima, então pensei em compartilhar para outras pessoas usarem. Espero que seja útil.
fonte
Eu tentei muito com diferentes abordagens. E, finalmente, aperfeiçoo um dos métodos. Primeiro, você precisa criar uma coleção separada e salvar todos os eventos. Segundo, você precisa criar um novo lambda para ser acionado pelo tempo. Este lambda Contará eventos na coleção de eventos e limpará os documentos do evento. Detalhes do código no artigo. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
fonte
Esta consulta resultará na contagem de documentos.
fonte
fonte