Migração para Neo4j — um estudo de caso — Parte 1

Remodelando os dados do Titanic para uma estrutura em grafo

Neylson Crepalde
3 min readFeb 13, 2023
Photo by JJ Ying on Unsplash

Neo4j hoje é uma das principais soluções do mercado para database em grafos. É uma ferramenta madura, já adotada em importantes organizações no mundo e que promete entregar um desempenho muito superior em comparação às databases relacionais.

Parte desse desempenho está diretamente relacionado à modelagem dos dados no formato de grafos, o qual é bem diferente da modelagem relacional clássica. O objetivo deste post é compartilhar um estudo de caso de remodelagem de uma tabela relacional para uma estrutura em grafo e, desse modo, otimizar as consultas. Vamos utilizar o (famoso) dataset do Titanic.

Modelagem de dados para grafos

Originalmente, o dataset do Titanic possui uma estrutura tabular.

Elaboração do autor

Observando a estrutura do dado, uma tentativa óbvia de modelagem seria reproduzir o grão da tabela como entidade base do grafo e todas as outras colunas como propriedades.

Elaboração do autor com arrows.app

O problema com esse modelo é que ele não se aproveita em nada da estrutura em grafo. Não há um laço (uma conexão) sequer mapeado no modelo. Dessa forma, de fato, o dado disposto num formato tabular seria muito mais performático.

No entanto, é necessário identificar, junto ao negócio, quais são os principais vetores de pesquisa e análise nesse dado para otimizar o nosso modelo. Depois dessa conversa, nosso time de negócio nos diz que análises relacionadas à classe que as pessoas viajavam e ao portão que elas entraram são muito relevantes (pelo menos aqui na nossa brincadeira 🙃).

Nesse caso, podemos alterar o modelo colocando a Classe e o Portão como entidades e pensando dois relacionamentos: passageiros EMBARCARAM_EM portão e passageiros estão NA_CLASSE classe. Traduzindo para o inglês e formalizando o desenho do modelo, temos algo assim:

Elaboração do autor com arrows.app

Isso possibilita aproveitarmos o melhor da estrutura de grafos nativa do Neo4j otimizando muito as consultas. Mas como isso funciona? Como a consulta é otimizada?

Entendendo o método de busca dos grafos

Há uma diferença essencial no método das consultas em tabelas relacionais e nas databases em grafos. Pegue a consulta abaixo como exemplo:

SELECT 
PassengerId, Pclass, Embarked
FROM titanic
WHERE
Pclass = 1
AND Embarked = 'S'

Para que uma database relacional consiga retornar os passageiros que viajavam na primeira classe e embarcaram no portão “S”, ela vai (via de regra) percorrer TODOS os casos da tabela e testar, um por um, se a condição descrita é satisfeita. Os casos em que a condição for satisfeita serão retornados. Não é difícil entender, no caso de termos uma tabela muito grande, por que essa consulta pode demorar algum tempo para ser executada.

Agora observe a mesma consulta numa estrutura em grafo em Cypher:

MATCH (p:Passenger)-[r:IN_CLASS]->(c:Class)
MATCH (p)-[e:EMBARKED_IN]->(g:Gate)
WHERE c.id = '1' AND g.id = 'S'
RETURN p, r, c, e, g;

Embora a consulta seja estritamente a mesma, o modo de execução difere bastante. Neo4j vai tomar os nós "Classe 1" e "Portão S" como ponto de partida e buscar apenas os nós que possuem relacionamento com os pontos de partida. Esse movimento é conhecido como traversal. O modo como Neo4j "atravessa" o grafo a partir dos pontos de partida ignorando completamente os caminhos que não estão na rota de busca otimiza muito a consulta.

No próximo post

No próximo post, vamos operacionalizar a ingestão de dados e realização de consultas utilizando Cypher. Nos vemos lá!

--

--