Estágio 02 · 02-16
LockedAlgumas queries são natural-mente caminhos em grafos: amigos de amigos, recomendação por co-purchase, fraud rings, dependências entre serviços, conhecimento corporativo, roteamento (Logística!). SQL pode resolver, JOINs recursivos, CTEs, mas vira ilegível e lento à medida que profundidade cresce.
Graph databases (Neo4j, Memgraph, ArangoDB, JanusGraph, AWS Neptune) tratam relacionamento como cidadão de primeira classe. Queries declarativas (Cypher, Gremlin, SPARQL) expressam "encontre caminho de A pra B com restrições" diretamente. Indexação de adjacency e algoritmos builtin (PageRank, betweenness, shortest path) executam em milissegundos onde SQL recursivo demora segundos.
Este módulo é graph DB por dentro: property graph model, native vs non-native graph (storage), Cypher (mais comum), traversal patterns, graph algorithms (BFS/DFS/Dijkstra/A*/PageRank/community detection), e quando NÃO usar graph DB (relacionamento simples cabe em SQL com índice; profundidade rasa não justifica nova stack).
(subject, predicate, object). Web semântica, ontologias, SPARQL. Dataset abertos (DBpedia, Wikidata).Property graph é mais conveniente pra apps; RDF brilha em integração de fontes heterogêneas e raciocínio formal.
Native graph storage (Neo4j, Memgraph): adjacency direta, pointer hopping. Traversal é cache-friendly. Non-native (graph layer sobre KV ou doc DB): traversal traduz em scans. Mais flexível em deployment, mas pode ter custo de hop.
Native shines em deep traversals (4+ hops). Non-native ok pra rasos.
Cypher (Neo4j) e openCypher (Memgraph, AWS Neptune adoption) usam ASCII art:
MATCH (u:User {id: $userId})-[:FRIEND]->(f)-[:FRIEND]->(fof)
WHERE NOT (u)-[:FRIEND]->(fof) AND u <> fof
RETURN fof.name, count(*) as common_friends
ORDER BY common_friends DESC
LIMIT 10
Sintaxe lê como o pattern: nodes em parênteses, relationships em colchetes com setas. MATCH, WHERE, RETURN, OPTIONAL MATCH, WITH (encadeia subqueries), MERGE (upsert).
Cypher suporta *N..M em relationships:
MATCH path = (a:Stop)-[:NEXT*1..5]->(b:Stop)
WHERE a.id = $start AND b.id = $end
RETURN path, length(path) ORDER BY length(path) LIMIT 1
Encontra caminhos de 1 a 5 hops. Sem profundidade, pode explodir, sempre limite.
Neo4j tem label/property index (B-Tree style) pra encontrar start nodes. Traversal subsequente é por adjacency, não índice.
Indexes textuais (full-text via Lucene), spatial (point), composite. Constraint unique disponível.
Bibliotecas de graph DBs (Neo4j GDS, Memgraph MAGE) entregam algoritmos:
Estes são algoritmos clássicos (01-05) com implementações otimizadas pra graph storage.
Regra: substantivos com identidade = nodes. Verbos/relacionamentos = edges. Properties em ambos.
Mas granularidade importa. Caso clássico: order com items.
(:Order)-[:CONTAINS]->(:Item). Se Item é compartilhado (mesmo SKU em vários orders), bom.(:Order)-[:CONTAINS {qty: 3}]->(:Product). Quantity vira property da edge, natural pra muitos:muitos com atributos.Anti-pattern: tudo node. Edges com properties são poderosos, use.
Neo4j ACID, transações multi-statement. Cluster mode usa Raft pra core (writes), read replicas. Em deploys grandes, sharding (Neo4j Fabric) divide por subdomínio mas adiciona complexidade.
Memgraph: in-memory, persistência via WAL+snapshots; transações ACID.
Regra: se você está escrevendo CTEs recursivos e queries com 4+ joins explorando relacionamentos, considere graph. Se não, fique em SQL.
Postgres com ltree (labels hierárquicas), WITH RECURSIVE (CTEs), e hand-rolled adjacency lists resolvem grafos médios. Extension Apache AGE roda Cypher sobre Postgres.
Trade-off: stack única, sem precisar de Neo4j. Mas perde algoritmos otimizados nativos.
Confusão comum. GraphQL é API query language (04-05), executada por resolvers que falam com qualquer storage (incluindo SQL). Graph DB é storage. GraphQL pode usar graph DB ou não.
Hop count é principal cost driver. Latency cresce ~ linear com profundidade (em native), exponencial com fan-out (sem filtro).
Optimization patterns:
*1..5, não *.Backups: hot backup com snapshot + replication. Neo4j Aura (managed). Sizing: dataset cabe em RAM idealmente; warm cache crítico.
Migration: import via LOAD CSV, apoc.periodic.iterate. Batch sizes 10k-50k.
Monitoring: Bolt protocol metrics, slow query log, page cache hit ratio.
ISO/IEC 39075:2024 (GQL) é primeiro standard internacional pra graph query language. Cypher é base. Adoção por Neo4j, AWS Neptune, TigerGraph. Vale acompanhar.
Você precisa, sem consultar:
Estender a Logística com roteamento de entregas via graph DB.
(:Stop {id, address, lat, lng, type: 'pickup'|'dropoff'|'hub'}).(:Courier {id, vehicle_type, capacity_kg}).(:Order {id, weight_kg, deadline, status}).(s1)-[:ROAD {distance_km, avg_minutes, traffic_factor}]->(s2).(:Order)-[:PICKUP_AT]->(:Stop), (:Order)-[:DROPOFF_AT]->(:Stop).(:Courier)-[:CARRIES]->(:Order).POST /assign (atribui melhor courier).GET /route/:courier_id retorna sequência de stops com tempo previsto.WITH RECURSIVE. Compare latência e legibilidade. Documente em comparison.md.comparison.md mostra Postgres recursive ≥ 5x mais lento e mais verboso.WITH RECURSIVE + AGE.