Quand tu tapes trois mots dans Google et que la réponse arrive en une fraction de seconde, avec tes fautes corrigées, ce n'est pas une base SQL qui parcourt des milliards de pages : c'est un index inversé, un dictionnaire « mot → pages qui le contiennent ». Elasticsearch et OpenSearch appliquent exactement ce principe à tes propres données. Et quand Netflix te propose « les gens qui ont aimé ceci ont aussi regardé… », ou que Facebook te suggère un ami d'ami, ce sont des relations qu'on parcourt, pas des lignes qu'on filtre : c'est le travail d'une base de graphes comme Neo4j.
| Qui | Outil | Pour quoi |
|---|---|---|
| Wikipédia | Elasticsearch | la barre de recherche de tous les articles, dans toutes les langues, tolérante aux fautes |
| Netflix, Uber, Slack | Elasticsearch + Kibana | des milliards de lignes de journaux par jour, explorées en direct pour trouver une panne en quelques secondes |
| Stack Overflow, GitHub | Elasticsearch | la recherche plein texte de questions, de réponses et de code |
| Amazon | OpenSearch | le moteur qu'Amazon a créé et maintient pour garder une version 100 % open source, vendu en service géré sur AWS |
| NASA | Neo4j | la base des « leçons apprises » de 50 ans de missions, reliées entre elles pour retrouver un précédent en quelques sauts |
| Consortium ICIJ (Panama Papers) | Neo4j | 11,5 millions de documents et les liens entre sociétés-écrans, dirigeants et banques, explorés en graphe par 370 journalistes |
| eBay, Walmart | Neo4j | recommandations en temps réel : « ceux qui ont acheté ceci… », calculées en suivant les relations d'achat |
Ce que ces entreprises ont en commun : elles ont aussi des bases SQL, pour les paiements, les commandes, les factures. Elles ajoutent un moteur de recherche à côté pour chercher, et une base de graphes à côté pour relier. C'est exactement ce que tu vas monter dans ce labo, en petit.
Imagine une grande école en ligne. À l'accueil, une documentaliste retrouve en une seconde tous les cours qui parlent de « déployer des conteneurs », même si tu as écrit « deploiement » sans accent : c'est Elasticsearch. Au mur, des écrans affichent le trafic du site en direct, les pages en erreur, les pays d'origine des visiteurs : c'est Kibana, qui ne stocke rien mais dessine ce qu'Elasticsearch contient. Dans le bureau d'orientation, une conseillère connaît les liens entre les gens : qui a suivi quoi, quel cours est prérequis de quel autre, quels étudiants se ressemblent : c'est Neo4j. Et OpenSearch ? C'est la documentaliste jumelle, formée dans la même école qu'Elasticsearch, embauchée par ceux qui veulent un contrat 100 % open source. Quatre outils, deux façons de ranger l'information : par mots (moteur de recherche) ou par liens (graphe).
| Outil | Version du labo | Rôle | Tu lui parles avec |
|---|---|---|---|
| Elasticsearch | 9.5.3 | stocke des documents JSON et les retrouve par le texte, les filtres, les agrégations | Query DSL (JSON), ES|QL |
| Kibana | 9.5.3 | interface web d'Elasticsearch : Dev Tools, Discover, Lens, tableaux de bord | des clics, KQL, et Dev Tools pour le JSON |
| OpenSearch (+ Dashboards) | 3.8.0 | fork open source d'Elasticsearch et de Kibana, même API à 95 % | la même Query DSL, plus SQL et PPL |
| Neo4j Community | 5.26 | base de graphes : nœuds, relations, propriétés | Cypher |
Elasticsearch et OpenSearch partagent le même moteur interne, Apache Lucene, et le même principe : l'index inversé. Plutôt que de lire chaque document à chaque recherche, le moteur construit une fois pour toutes un dictionnaire « mot → liste des documents qui le contiennent ». Chercher « docker kubernetes » revient alors à croiser deux listes d'identifiants, ce qui prend quelques millisecondes sur des millions de documents. Neo4j fait un pari opposé : il stocke les relations comme des pointeurs physiques entre nœuds, si bien que « les amis de mes amis » se calcule en suivant des flèches, sans jointure.
Chaque moteur invente ses mots, mais ils désignent souvent la même idée qu'en base relationnelle. Ce tableau traduit les termes de base entre le SQL classique, les moteurs de recherche et le graphe.
| SQL classique | Elasticsearch / OpenSearch | Neo4j (graphe) | En clair |
|---|---|---|---|
| base de données | cluster (ensemble d'index) | base de graphe | tout le contenu géré par le serveur |
| table | index | étiquette de nœud (label) | une collection d'éléments de même type |
| ligne / enregistrement | document (JSON) | nœud | un élément |
| colonne | champ (field) | propriété | un attribut de l'élément |
| schéma / DDL | mapping | schéma souple (facultatif) | la définition des types de champs |
| clé primaire | _id du document | identité du nœud | l'identifiant unique |
| clé étrangère + jointure | pas de jointure : cours_id dénormalisé | relation (-[:PREREQUIS_DE]->) | le lien entre deux éléments |
| index (B-tree) d'accélération | index inversé | index sur une propriété | la structure qui accélère la recherche |
SELECT … WHERE | Query DSL (JSON), ES|QL | MATCH … WHERE … RETURN | interroger les données |
GROUP BY / agrégat | agrégations (aggs) | count(), collect() | regrouper et compter |
| SQL (langage) | Query DSL / ES|QL / KQL | Cypher | le langage de requête |
Attention au mot « index ». En SQL, un index est une structure d'accélération (B-tree) posée sur une table. Dans Elasticsearch, un index est l'équivalent de la table elle-même. Et l'index inversé est encore autre chose : le mécanisme interne « mot → documents » qui rend la recherche instantanée. Trois sens pour un seul mot.
Prenons trois notions de notre école : des cours, des étudiants, des avis laissés par les étudiants sur les cours.
1. En SQL (tables et jointures) — trois tables normalisées, l'information n'est jamais dupliquée, les liens passent par des clés étrangères :
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;Parfait pour la cohérence (une note modifiée est modifiée partout), moins bon pour « tous les cours dont la description contient déployer » : LIKE '%déploy%' parcourt toute la table.
2. En documents (Elasticsearch / OpenSearch) — un cours est un seul document JSON qui embarque ce dont la recherche a besoin, y compris le nom du professeur et la note moyenne déjà calculée. Voici, tel quel, le premier document de l'index cours du labo :
{
"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"]
}Le nom du professeur est dénormalisé (copié dans chaque cours). S'il change de nom, il faudra réindexer ses cours : c'est le prix de la recherche instantanée. Les avis vivent dans un second index, avis, avec le cours_id en simple champ, sans jointure possible au moment de la requête.
3. En graphe (Neo4j) — les mêmes notions deviennent des nœuds, et les liens deviennent des relations de première classe qui portent elles-mêmes des propriétés. Voici trois relations réelles du graphe du labo autour du cours 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"})La question « quels cours ont suivi les étudiants qui ont aimé le même cours que moi ? » s'écrit en une ligne de Cypher et se calcule en suivant trois relations, là où SQL enchaînerait trois jointures et où Elasticsearch ne saurait tout simplement pas répondre.
| Question | Meilleur outil | Pourquoi |
|---|---|---|
| « cours sur déployer des conteneurs, tolérant aux fautes » | Elasticsearch / OpenSearch | index inversé, analyseur français, fuzzy |
| « répartition des erreurs 500 par pays sur 30 jours » | Elasticsearch + Kibana | agrégations et visualisation temps réel |
| « chemin de prérequis pour arriver au cours C0230 » | Neo4j | parcours de relations, plus court chemin |
| « recommander un cours à partir des inscriptions similaires » | Neo4j | filtrage collaboratif = motif de graphe |
| « paiement, facture, cohérence stricte » | SQL (hors labo) | transactions ACID |
Dans la vraie vie, les journaux arrivent en continu (Filebeat, Logstash ou l'application elle-même) et la base de graphes est alimentée par le système métier. Dans le labo, deux commandes remplacent tout cela : importer envoie les fichiers NDJSON à l'API _bulk d'Elasticsearch, charger-graphe exécute un script Cypher qui lit des CSV. Les deux mondes ne communiquent pas entre eux : c'est toi, ou ton application, qui choisis à qui poser chaque question.
Rien à taper dans cette leçon : le labo se démarre en leçon 03. Les extraits ci-dessous ont été relevés sur le labo du cours, pour que tu saches ce que tu vas trouver dedans.
Le jeu de données : une plateforme de cours en ligne. Un seul univers alimente les trois moteurs, pour comparer ce que chacun fait de mieux.
| Jeu | Volume exact | Contenu |
|---|---|---|
index cours | 504 documents | titre, description (analyseur français), catégorie, sujet, niveau, prix, tags, note moyenne, professeur |
index avis | 609 documents | note de 1 à 5, texte, prénom, ville, pays, date, votes « utile » |
index acces | 12 000 lignes | journaux web du 2026-08-10 au 2026-09-08 : chemin, statut HTTP, IP, pays, appareil, référent |
| graphe Neo4j | 872 nœuds · 3 712 relations | Cours 504, Etudiant 300, Professeur 30, Competence 22, Ville 16 |
Ce qu'il faut voir : les 504 cours du graphe sont les mêmes que ceux de l'index cours (mêmes identifiants C0001…C0504). Tu pourras chercher un cours dans Elasticsearch puis explorer ses prérequis dans Neo4j.
Les catégories sont parfaitement équilibrées. Une agrégation terms sur categorie renvoie :
Cloud 84 · DevOps 84 · Données 84 · Développement web 84 · IA 84 · Sécurité 84Et sur les autres champs : niveau → debutant 252, avance 158, intermediaire 94 ; langue → fr 375, en 129 ; gratuit → 75 cours gratuits ; 72 sujets distincts (Docker, Kubernetes, Elasticsearch, Neo4j, React, AWS…) ; 30 professeurs. Ce qu'il faut voir : des chiffres ronds et connus d'avance, pratiques pour vérifier tes requêtes des modules 2 et 3.
Un avis, tel qu'il est stocké. Premier document de l'index 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 }Ce qu'il faut voir : cours_id est une simple chaîne. Aucune jointure ne relie cet avis à son cours dans Elasticsearch ; c'est ton application qui fera le lien.
Une ligne de journal. La plus récente de l'index 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" }Sur les 12 000 lignes : 10 829 en 200, 403 en 404, 355 en 301, 235 en 304, 122 en 500, 56 en 503. Ce qu'il faut voir : le champ @timestamp, indispensable à Kibana Discover pour l'axe du temps (module 4).
Le graphe, compté par étiquette et par type de relation. Résultat réel de deux requêtes Cypher :
Cours 504 · Etudiant 300 · Professeur 30 · Competence 22 · Ville 16
INSCRIT_A 1654 · COUVRE 994 · ENSEIGNE 504 · HABITE 330 · PREREQUIS_DE 230Ce qu'il faut voir : 1 654 inscriptions pour 300 étudiants, soit environ 5,5 cours par étudiant. C'est ce maillage qui rendra les recommandations du module 7 intéressantes.
« Je connais SQL, pourquoi ne pas tout faire avec PostgreSQL ? » → Tu peux, jusqu'à un certain point. PostgreSQL sait faire de la recherche plein texte et des requêtes récursives. Mais dès que tu veux la tolérance aux fautes, le classement par pertinence, des agrégations sur des millions de lignes en temps réel ou des parcours de graphe à profondeur variable, chaque moteur spécialisé fait le travail en quelques millisecondes là où SQL demande des index exotiques et des requêtes illisibles. Le bon réflexe : SQL pour la source de vérité transactionnelle, Elasticsearch à côté pour chercher, Neo4j à côté pour relier.
« Elasticsearch ou OpenSearch, je dois choisir maintenant ? » → Non. Le cours te fait travailler sur Elasticsearch ; le module 5 rejoue les mêmes requêtes sur OpenSearch et liste les différences (une poignée). Ce que tu apprends vaut pour les deux.
« Kibana, c'est une base de données ? » → Non, et c'est une confusion fréquente. Kibana ne stocke que ta configuration (tableaux de bord, vues) dans un index caché d'Elasticsearch. Toutes les données que tu vois viennent d'Elasticsearch ; si Elasticsearch est arrêté, Kibana affiche « Kibana server is not ready yet » (leçon 04).
Le mot « index » désigne deux choses différentes : en SQL, une structure d'accélération (B-tree) attachée à une table ; dans Elasticsearch, l'équivalent de la table elle-même, découpé en shards (des index Lucene autonomes). Le module 2, leçon 01, reprend ce vocabulaire en pratique sur le labo.