Consultas SQL no Firebase

Kheronn K. Machado
5 min readMay 24, 2019

Entre os recursos que a plataforma de serviços Firebase disponibiliza está o Cloud Firestore. Trata-se de um banco de dados NoSQL hospedado nas nuvens onde armazenamos os dados em documentos.

A consulta de dados deste banco é eficiente é flexível, mas há diferenças se você já desenvolve com SQL.

Nesse artigo apresento o FireSql. Uma biblioteca criada com base no SDK oficial do Firebase que permite

consultar coleções no Cloud Firestore usando a sintaxe SQL.

Vamos criar três coleções e alguns documentos para criar consultas sql. Um projeto em Angular 7 foi criado e as funções de exemplos estão todas no componente principal.

No final do artigo colocarei o link do projeto no Github.

Criando as Coleções. Acessando o console do firebase com suas credenciais google e crie um projeto. Para mais detalhes, veja meu artigo.

Vamos criar as coleções para executar as consultas.

Criei 3 coleções nomeando como cidades, estados e pessoas.

Para estados eu criei alguns documentos com os campos nome e sigla.

Para cidades foram 3 campos, nome, uf como string e populacao (sem ~ ç) como number. Também criei alguns documentos.

Finalmente para a coleção pessoas, desenvolvi os seguintes campos:

Indiquei o nome como string, idade como number, tags como array e um map endereco com os campos bairro, numero e rua. Assim como as coleções anteriores, também criei mais documentos para a realização das consultas.

Finalizado a inclusão de valores, o próximo passo é instalar a biblioteca.

Após criar um projeto com o Angular CLI, no terminal do projeto vamos informar:

npm install firesql firebase

Assim adicionamos as bibliotecas do Firebase e o FireSql.

No componente principal, vamos iniciar realizando os seguintes imports:

import { Component, OnInit } from ‘@angular/core’;import { FireSQL } from ‘firesql’;import * as firebase from ‘firebase/app’;import ‘firebase/firestore’;

Dessa forma podemos declarar os objetos necessários para a realização das consultas.

Na sequência podemos declarar um objeto que realizará as consultas, definindo também as configurações para conectar no firebase:

fireSQL;constructor() {let firebaseConfig = {    apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>',
messagingSenderId: 'seus-dados',
appId: 'seus-dados'
};
firebase.initializeApp(firebaseConfig);this.fireSQL = new FireSQL(firebase.firestore());}

No método construtor definimos as configurações do projeto obtidas na página do projeto no Firebase, inicializando o app e instanciando o objeto fireSQL.

A partir deste momento já podemos escrever as consultas.

Vamos começar testando operador WHERE na coleção cidades. O objetivo é apresentar todos os documentos que tem a uf do paraná e a população superior a dez mil.

A função ficou assim:

consultaComWhere() {const cidades = this.fireSQL.query(`SELECT  nome as cidade, uf, populacaoFROM cidadesWhere uf = 'PR' and populacao > 10000`);cidades.then(lista => {for (let cidade of lista) {console.log(`${cidade.cidade} -  UF: ${cidade.uf} - População: ${cidade.populacao}`)}})}

Utilizamos a sintaxe clássica do SQL utilizando SELEC FROM e ainda usamos um alias para o campo nome.

O método query retorna uma promise pelo qual podemos recuperar no callback o array do resultado.

Realizamos um loop para exibir no console as propriedades cidade, uf e populacao.

Para testar, chamamos a função no método ngOnInit().

ngOnInit(): void {this.consultaComWhere()}

O resultado no console:

Podemos utilizar o operador LIKE para campos do tipo string, usando o curinga %.

consultaComLike() {const estados = this.fireSQL.query(`SELECT  * FROM estadosWHERE nome LIKE 'P%'`);estados.then(lista => {for (let uf of lista) {console.log(`${uf.nome} -  UF: ${uf.sigla} `)}})}

No console a relação de todos os estados iniciados com a letra P

Podemos definir um conjunto de valores no parâmetro utilizando o IN:

consultaComIN() {const cidades = this.fireSQL.query(`SELECT  nome as cidade, uf, populacaoFROM cidadesWHERE uf IN ('PR', 'SP')`);cidades.then(lista => {for (let cidade of lista) {console.log(`${cidade.cidade} -  UF: ${cidade.uf} - População: ${cidade.populacao}`)}})}

E o resultado:

Cidades de São Paulo e do Paraná.

Uma forma comum de modelar em NoSQL é a utilização de objetos aninhados. Utilizamos essa abordagem na propriedade endereco da pessoa. Para fazer consultas devemos usar as propriedades entre acentos graves:

consultaComObjetoAninhado() {const pessoas = this.fireSQL.query(`SELECT  nome, endereco FROM pessoasWHERE \`endereco.bairro\` = 'Centro'`);pessoas.then(lista => {console.log(lista)for (let pessoa of lista) {console.log(`${pessoa.nome} - Endereco: ${pessoa.endereco.rua} Bairro: ${pessoa.endereco.bairro} `)}})}

Definimos uma consulta que retorne todos os registros de pessoas do Centro. Observe que devemos usar as barras invertidas pois já estamos usando o ` no início da consulta.

Na próxima função vamos implementar verificando o conteúdo de um campo do tipo array. Usaremos o operador CONTAINS:

consultaArrays() {const pessoas = this.fireSQL.query(`SELECT  nome, endereco, tags FROM pessoasWHERE tags CONTAINS 'saúde'`);pessoas.then(lista => {console.log(lista)for (let pessoa of lista) {console.log(`${pessoa.nome} - Interesses: ${JSON.stringify(pessoa.tags)}`)}})}

Resultado:

Verificamos no campo tags o valor saúde. Para exibir utilizamos a função JSON.stringify.

Podemos também realizar cálculos como média, mínimo e máximo dos valores. A função seguinte apresenta a implementação:

consultaEstatistica() {const estatistica = this.fireSQL.query(`SELECT MIN(idade) as minimo, AVG(idade) as media, MAX(idade) as maximoFROM pessoas`);estatistica.then(lista => {console.log(lista)for (let estatistica of lista) {console.log(`Mínimo: ${estatistica.minimo} - Máximo: ${estatistica.maximo} - Média: ${estatistica.media}`)}})}

O console ficou:

Infelizmente a biblioteca ainda tem algumas restrições e limites como:

  • Somente SELECT por enquanto. Há previsão para implementações futuras par INSERT, UPDATE e DELETE;
  • Não suporta JOINs nem negação NOT :(
  • LIMIT não aceita OFFSET somente um número
  • GROUP BY não pode ser utilizado com ORDER BY

De qualquer forma, é uma biblioteca muito interessante, pois é ajustada para criar uma quantidade mínima de consultas nos servidores do Firebase.

Fica a dica.

Links

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Kheronn K. Machado
Kheronn K. Machado

Written by Kheronn K. Machado

Professor, pesquisador e desenvolvedor.

Responses (1)

Write a response