Quando você digita três palavras no Google e a resposta chega em uma fração de segundo, com seus erros de digitação corrigidos, não é um banco SQL que percorre bilhões de páginas: é um índice invertido, um dicionário "palavra → páginas que a contêm". Elasticsearch e OpenSearch aplicam exatamente esse princípio aos seus próprios dados. E quando a Netflix propõe "quem gostou disto também assistiu…", ou quando o Facebook sugere um amigo de amigo, são relações que se percorrem, não linhas que se filtram: é o trabalho de um banco de dados de grafos como o Neo4j.
| Quem | Ferramenta | Para quê |
|---|---|---|
| Wikipédia | Elasticsearch | a barra de busca de todos os artigos, em todos os idiomas, tolerante a erros de digitação |
| Netflix, Uber, Slack | Elasticsearch + Kibana | bilhões de linhas de logs por dia, exploradas ao vivo para encontrar uma falha em alguns segundos |
| Stack Overflow, GitHub | Elasticsearch | a busca full-text de perguntas, respostas e código |
| Amazon | OpenSearch | o motor que a Amazon criou e mantém para conservar uma versão 100% open source, vendido como serviço gerenciado na AWS |
| NASA | Neo4j | a base de "lições aprendidas" de 50 anos de missões, interligadas para reencontrar um precedente em alguns saltos |
| Consórcio ICIJ (Panama Papers) | Neo4j | 11,5 milhões de documentos e os vínculos entre empresas de fachada, dirigentes e bancos, explorados em grafo por 370 jornalistas |
| eBay, Walmart | Neo4j | recomendações em tempo real: "quem comprou isto…", calculadas seguindo as relações de compra |
O que essas empresas têm em comum: elas também têm bancos SQL, para os pagamentos, os pedidos, as faturas. Elas acrescentam um motor de busca ao lado para buscar, e um banco de grafos ao lado para relacionar. É exatamente o que você vai montar neste laboratório, em pequena escala.
Imagine uma grande escola online. Na recepção, uma bibliotecária encontra em um segundo todos os cursos que falam de "implantar contêineres", mesmo que você tenha escrito "deploiement" sem acento: é o Elasticsearch. Na parede, telas exibem o tráfego do site ao vivo, as páginas com erro, os países de origem dos visitantes: é o Kibana, que não armazena nada mas desenha o que o Elasticsearch contém. Na sala de orientação, uma conselheira conhece os vínculos entre as pessoas: quem cursou o quê, qual curso é pré-requisito de qual outro, quais estudantes se parecem: é o Neo4j. E o OpenSearch? É a bibliotecária gêmea, formada na mesma escola que o Elasticsearch, contratada por quem quer um contrato 100% open source. Quatro ferramentas, duas maneiras de organizar a informação: por palavras (motor de busca) ou por vínculos (grafo).
| Ferramenta | Versão do laboratório | Papel | Você fala com ela usando |
|---|---|---|---|
| Elasticsearch | 9.5.3 | armazena documentos JSON e os recupera pelo texto, pelos filtros, pelas agregações | Query DSL (JSON), ES|QL |
| Kibana | 9.5.3 | interface web do Elasticsearch: Dev Tools, Discover, Lens, painéis | cliques, KQL, e Dev Tools para o JSON |
| OpenSearch (+ Dashboards) | 3.8.0 | fork open source do Elasticsearch e do Kibana, mesma API em 95% | a mesma Query DSL, mais SQL e PPL |
| Neo4j Community | 5.26 | banco de grafos: nós, relações, propriedades | Cypher |
Elasticsearch e OpenSearch compartilham o mesmo motor interno, Apache Lucene, e o mesmo princípio: o índice invertido. Em vez de ler cada documento a cada busca, o motor constrói de uma vez por todas um dicionário "palavra → lista dos documentos que a contêm". Buscar "docker kubernetes" se resume então a cruzar duas listas de identificadores, o que leva alguns milissegundos sobre milhões de documentos. O Neo4j faz uma aposta oposta: ele armazena as relações como ponteiros físicos entre nós, de modo que "os amigos dos meus amigos" se calcula seguindo setas, sem junção.
Cada motor inventa suas palavras, mas elas designam frequentemente a mesma ideia que em um banco relacional. Esta tabela traduz os termos básicos entre o SQL clássico, os motores de busca e o grafo.
| SQL clássico | Elasticsearch / OpenSearch | Neo4j (grafo) | Em termos simples |
|---|---|---|---|
| banco de dados | cluster (conjunto de índices) | banco de grafos | todo o conteúdo gerenciado pelo servidor |
| tabela | índice | rótulo de nó (label) | uma coleção de elementos do mesmo tipo |
| linha / registro | documento (JSON) | nó | um elemento |
| coluna | campo (field) | propriedade | um atributo do elemento |
| esquema / DDL | mapping | esquema flexível (opcional) | a definição dos tipos de campos |
| chave primária | _id do documento | identidade do nó | o identificador único |
| chave estrangeira + junção | sem junção: cours_id desnormalizado | relação (-[:PREREQUIS_DE]->) | o vínculo entre dois elementos |
| índice (B-tree) de aceleração | índice invertido | índice sobre uma propriedade | a estrutura que acelera a busca |
SELECT … WHERE | Query DSL (JSON), ES|QL | MATCH … WHERE … RETURN | consultar os dados |
GROUP BY / agregado | agregações (aggs) | count(), collect() | agrupar e contar |
| SQL (linguagem) | Query DSL / ES|QL / KQL | Cypher | a linguagem de consulta |
Atenção à palavra "índice". Em SQL, um índice é uma estrutura de aceleração (B-tree) colocada sobre uma tabela. No Elasticsearch, um índice é o equivalente da própria tabela. E o índice invertido é ainda outra coisa: o mecanismo interno "palavra → documentos" que torna a busca instantânea. Três sentidos para uma única palavra.
Tomemos três noções da nossa escola: cursos, estudantes, avaliações deixadas pelos estudantes sobre os cursos.
1. Em SQL (tabelas e junções) — três tabelas normalizadas, a informação nunca é duplicada, os vínculos passam por chaves estrangeiras:
SELECT c.titre, AVG(a.note)
FROM cours c
JOIN avis a ON a.cours_id = c.id
JOIN etudiant e ON e.id = a.etudiant_id
WHERE e.ville = 'Montréal'
GROUP BY c.titre;Perfeito para a consistência (uma nota modificada é modificada em todos os lugares), menos bom para "todos os cursos cuja descrição contém déployer": LIKE '%déploy%' percorre a tabela inteira.
2. Em documentos (Elasticsearch / OpenSearch) — um curso é um único documento JSON que embarca o que a busca precisa, inclusive o nome do professor e a nota média já calculada. Eis, tal como está, o primeiro documento do índice cours do laboratório:
{
"id": "C0001",
"titre": "Docker expliqué simplement",
"description": "Dans ce cours accessible sans prérequis, vous apprenez à automatiser vos applications avec Docker. …",
"categorie": "DevOps", "sujet": "Docker", "niveau": "debutant", "langue": "en",
"prix": 129, "gratuit": false, "duree_heures": 5,
"tags": ["docker", "linux", "helm", "devops"],
"date_publication": "2024-08-14",
"note_moyenne": 4.4, "nb_avis": 327,
"professeur": { "id": "P001", "nom": "Karim Caron", "ville": "Gatineau" },
"competences": ["Conteneurisation", "Intégration continue"]
}O nome do professor está desnormalizado (copiado em cada curso). Se ele mudar de nome, será preciso reindexar seus cursos: é o preço da busca instantânea. As avaliações vivem em um segundo índice, avis, com o cours_id como simples campo, sem junção possível no momento da consulta.
3. Em grafo (Neo4j) — as mesmas noções se tornam nós, e os vínculos se tornam relações de primeira classe que carregam elas mesmas propriedades. Eis três relações reais do grafo do laboratório em torno do curso C0001:
(:Etudiant {prenom: "Hugo"})-[:INSCRIT_A {progression: 100, note: 4}]->(:Cours {id: "C0001", titre: "Docker expliqué simplement"})
(:Cours {id: "C0001"})-[:PREREQUIS_DE]->(:Cours {id: "C0003", titre: "Docker : le guide complet"})
(:Professeur {prenom: "Karim", nom: "Caron"})-[:ENSEIGNE]->(:Cours {id: "C0001"})A pergunta "quais cursos fizeram os estudantes que gostaram do mesmo curso que eu?" se escreve em uma linha de Cypher e se calcula seguindo três relações, onde o SQL encadearia três junções e onde o Elasticsearch simplesmente não saberia responder.
| Pergunta | Melhor ferramenta | Por quê |
|---|---|---|
| "cursos sobre implantar contêineres, tolerante a erros de digitação" | Elasticsearch / OpenSearch | índice invertido, analisador francês, fuzzy |
| "distribuição dos erros 500 por país em 30 dias" | Elasticsearch + Kibana | agregações e visualização em tempo real |
| "caminho de pré-requisitos para chegar ao curso C0230" | Neo4j | percurso de relações, caminho mais curto |
| "recomendar um curso a partir de inscrições similares" | Neo4j | filtragem colaborativa = padrão de grafo |
| "pagamento, fatura, consistência estrita" | SQL (fora do laboratório) | transações ACID |
Na vida real, os logs chegam continuamente (Filebeat, Logstash ou a própria aplicação) e o banco de grafos é alimentado pelo sistema de negócio. No laboratório, dois comandos substituem tudo isso: importer envia os arquivos NDJSON para a API _bulk do Elasticsearch, charger-graphe executa um script Cypher que lê CSVs. Os dois mundos não se comunicam entre si: é você, ou sua aplicação, quem escolhe a quem fazer cada pergunta.
Nada a digitar nesta lição: o laboratório é iniciado na lição 03. Os trechos abaixo foram coletados no laboratório do curso, para que você saiba o que vai encontrar nele.
O conjunto de dados: uma plataforma de cursos online. Um único universo alimenta os três motores, para comparar o que cada um faz melhor.
| Conjunto | Volume exato | Conteúdo |
|---|---|---|
índice cours | 504 documentos | título, descrição (analisador francês), categoria, assunto, nível, preço, tags, nota média, professor |
índice avis | 609 documentos | nota de 1 a 5, texto, primeiro nome, cidade, país, data, votos "útil" |
índice acces | 12.000 linhas | logs web de 2026-08-10 a 2026-09-08: caminho, status HTTP, IP, país, dispositivo, referenciador |
| grafo Neo4j | 872 nós · 3.712 relações | Cours 504, Etudiant 300, Professeur 30, Competence 22, Ville 16 |
O que é preciso ver: os 504 cursos do grafo são os mesmos que os do índice cours (mesmos identificadores C0001…C0504). Você poderá buscar um curso no Elasticsearch e depois explorar seus pré-requisitos no Neo4j.
As categorias estão perfeitamente equilibradas. Uma agregação terms sobre categorie retorna:
Cloud 84 · DevOps 84 · Données 84 · Développement web 84 · IA 84 · Sécurité 84E sobre os outros campos: niveau → debutant 252, avance 158, intermediaire 94; langue → fr 375, en 129; gratuit → 75 cursos gratuitos; 72 assuntos distintos (Docker, Kubernetes, Elasticsearch, Neo4j, React, AWS…); 30 professores. O que é preciso ver: números redondos e conhecidos de antemão, práticos para verificar suas consultas dos módulos 2 e 3.
Uma avaliação, tal como é armazenada. Primeiro documento do índice avis:
{ "id": "A00001", "cours_id": "C0028", "etudiant": "Nathan", "ville": "Sherbrooke", "pays": "Canada",
"note": 3, "texte": "Les vidéos sont bonnes, la partie théorique est dense.", "date": "2024-06-21", "utile": 33 }O que é preciso ver: cours_id é uma simples string. Nenhuma junção liga esta avaliação ao seu curso no Elasticsearch; é a sua aplicação que fará o vínculo.
Uma linha de log. A mais recente do índice acces:
{ "id": "L012000", "@timestamp": "2026-09-08T23:39:29.000Z", "methode": "GET", "chemin": "/cours/C0430",
"cours_id": "C0430", "categorie": "Cloud", "statut": 200, "octets": 168403, "duree_ms": 351,
"ip": "169.199.97.7", "pays": "CA", "appareil": "desktop", "navigateur": "Chrome", "referent": "direct" }Das 12.000 linhas: 10.829 em 200, 403 em 404, 355 em 301, 235 em 304, 122 em 500, 56 em 503. O que é preciso ver: o campo @timestamp, indispensável ao Kibana Discover para o eixo do tempo (módulo 4).
O grafo, contado por rótulo e por tipo de relação. Resultado real de duas consultas Cypher:
Cours 504 · Etudiant 300 · Professeur 30 · Competence 22 · Ville 16
INSCRIT_A 1654 · COUVRE 994 · ENSEIGNE 504 · HABITE 330 · PREREQUIS_DE 230O que é preciso ver: 1.654 inscrições para 300 estudantes, ou seja, cerca de 5,5 cursos por estudante. É essa malha que tornará as recomendações do módulo 7 interessantes.
"Eu conheço SQL, por que não fazer tudo com PostgreSQL?" → Você pode, até certo ponto. O PostgreSQL sabe fazer busca full-text e consultas recursivas. Mas assim que você quer tolerância a erros de digitação, classificação por relevância, agregações sobre milhões de linhas em tempo real ou percursos de grafo com profundidade variável, cada motor especializado faz o trabalho em alguns milissegundos onde o SQL exige índices exóticos e consultas ilegíveis. O bom reflexo: SQL para a fonte de verdade transacional, Elasticsearch ao lado para buscar, Neo4j ao lado para relacionar.
"Elasticsearch ou OpenSearch, preciso escolher agora?" → Não. O curso faz você trabalhar no Elasticsearch; o módulo 5 reexecuta as mesmas consultas no OpenSearch e lista as diferenças (um punhado). O que você aprende vale para os dois.
"Kibana é um banco de dados?" → Não, e é uma confusão frequente. O Kibana armazena apenas a sua configuração (painéis, visualizações) em um índice oculto do Elasticsearch. Todos os dados que você vê vêm do Elasticsearch; se o Elasticsearch estiver parado, o Kibana exibe "Kibana server is not ready yet" (lição 04).
A palavra "índice" designa duas coisas diferentes: em SQL, uma estrutura de aceleração (B-tree) anexada a uma tabela; no Elasticsearch, o equivalente da própria tabela, dividida em shards (índices Lucene autônomos). O módulo 2, lição 01, retoma esse vocabulário na prática, no laboratório.