Firebase Database para Desenvolvedores SQL — Queries avançadas

Agora que já sabemos realizar operações básicas e conhecemos algumas técnicas para ler dados na Firebase Realtime Database, está na hora de aprendermos algumas queries mais complexas.

Vamos começar por olhar para a dúvida que ficou aberta no artigo anterior:

Como encontrar todos os usuários com 21 anos e que vivem em Maputo?

No SQL é simples, basta utilizar a query:

SELECT * FROM usuarios WHERE idade=21 AND cidade = 'Maputo';

E seguindo a lógica das queries anteriores, no firebase para android, você provavelmente irá querer utilizar o orderByChild(‘idade’).equalTo(21) e orderByChild(‘cidade’).equalTo(‘Maputo’). Mas infelizmente, o firebase não permite utilizar 2 métodos de ordenação na mesma Query.

Por isso, como alternativa, podemos criar um novo atributo na nossa base de dados para armazenar a idade e a cidade. Vamos chamar-lhe de “idade_cidade”. E fica assim:

Assim, para encontrarmos todos os usuários com 21 anos e que vivem em Maputo, basta utilizar a query:

Query query1 = raiz.child('usuarios').orderByChild('idade_cidade').equalTo('21_maputo');

É como eu disse no artigo anterior: Devemos estruturar os nossos dados de acordo com a forma como eles serão dispostos na interface gráfica.

Encontrar os nomes do estudantes do grupo de id “am” (JOIN)

Em SQL, você provavelmente ia utilizar algo parecido com:

SELECT g.nome AS NomeGrupo, u.nome AS NomeUsuario FROM grupos AS g INNER JOIN estudantes AS est ON g.id = est.id_grupo INNER JOIN usuarios AS u ON u.id = est.id_estudante WHERE g.id = "am"; //Encontrar todos os participantes do grupo com ID "am" (Analise Matematica)

No Firebase não existe nenhum método específico para fazer JOIN, mas isso não significa que você não pode obter dados de 2 nós diferentes e juntá-los.

Para ter o nome dos estudantes do grupo “am”, basta utilizarmos a query:

Query query2 = raiz.child("estudantes/am");
//E colocamos um listener
query2.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//colocar os nomes na interface grafica
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
@Override
public void onCancelled(DatabaseError databaseError) {}
});

Repare que aqui nós utilizamos o ChildEventListener. Porque você provavelmente não vai precisar de manter os nomes sincronizados em tempo real, mas sim, actualizar a lista de participantes quando alguém entrar no grupo.

Mas desta forma, obtemos apenas os nomes dos estudantes, e não temos todos os dados deles. Para obter os outros dados, podemos criar uma referencia dentro desta query, já que temos o id do usuário.

@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
DatabaseReference usuario = raiz.child("usuarios/"+dataSnapshot.getKey());
usuario.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Obter os outros dados do usuario
    }

@Override
public void onCancelled(DatabaseError databaseError) {

}
});
    }

Como deu para notar, não existe uma forma “padrão” de estruturar bases de dados NoSQL. Ela pode variar de acordo com a aplicação que se está a desenvolver.

No próximo artigo, explico como usar a Denormalização para simplificar e reduzir queries.


Se você tem alguma dúvida ou sugestão, não hesite em me contactar pelo email rosariofernandes51@gmail.com ou pelo Telegram. Ficarei feliz por conversar com você. :)