Elasticsearch for Data Engineers
Ce module présente Elasticsearch, le moteur de recherche et d’analytics distribué.
Prérequis
| Niveau | Compétence |
|---|---|
| ✅ Requis | Avoir suivi le module 08_intro_big_data_distributed |
| ✅ Requis | Comprendre les 5V du Big Data |
| ✅ Requis | Comprendre CAP |
| ✅ Requis | Connaître le format JSON |
Objectifs du module
À la fin de ce notebook, tu seras capable de :
- Comprendre l’architecture Elasticsearch (index, shards, replicas)
- Utiliser Elasticvue pour interagir avec le cluster
- Créer des index avec mapping approprié
- Créer des Index Templates pour automatiser les mappings
- Indexer, rechercher, modifier et supprimer des documents
- Écrire des requêtes de recherche (match, bool, fuzzy, range)
- Réaliser des agrégations analytiques
Version Elasticsearch
Ce cours utilise Elasticsearch 8.x (version recommandée : 8.12+).
| Version | Notes |
|---|---|
| 8.x | ✅ Recommandée — Sécurité par défaut, nouvelles fonctionnalités |
| 7.x | ⚠️ Encore supportée mais migration conseillée |
| 6.x et avant | ❌ Obsolète |
💡 Les exemples de ce cours fonctionnent avec ES 7.x et 8.x. Pour ES 8.x, la sécurité est activée par défaut — nous la désactivons pour les tests locaux.
🎯 Elasticsearch dans l’écosystème Big Data
Tu as vu dans le module 08 les différents types de bases NoSQL. Elasticsearch est un moteur de recherche (Search Engine), parfois classé à part des bases NoSQL traditionnelles.
Position dans les types NoSQL
┌─────────────────────────────────────────────────────────────────┐
│ BASES NoSQL │
├───────────┬───────────┬───────────┬───────────┬────────────────┤
│ Document │ Clé-Valeur│ Colonnes │ Graphe │ Search Engine │
│ │ │ │ │ │
│ MongoDB │ Redis │ Cassandra │ Neo4j │ ELASTICSEARCH │
│ │ │ │ │ ◄─── │
└───────────┴───────────┴───────────┴───────────┴────────────────┘
Rappel : Les 5V
| V | Comment Elasticsearch répond |
|---|---|
| Volume | Sharding horizontal (données réparties sur plusieurs nœuds) |
| Velocity | Indexation temps réel, near real-time search |
| Variety | Documents JSON flexibles, analyse full-text |
| Veracity | Scoring de pertinence, recherche approximative |
| Value | Recherche instantanée, dashboards Kibana |
Rappel : CAP & BASE
| Concept | Elasticsearch |
|---|---|
| CAP | AP (Availability + Partition tolerance) par défaut |
| BASE | Eventually consistent (cohérence éventuelle) |
Pourquoi Elasticsearch en Data Engineering ?
| Cas d’usage | Description |
|---|---|
| Logs & Monitoring | Stack ELK (Elasticsearch, Logstash, Kibana) |
| Recherche full-text | Moteur de recherche pour sites web, e-commerce |
| Analytics temps réel | Dashboards et métriques en temps réel |
| Alerting | Détection d’anomalies, alertes sur seuils |
💡 ELK Stack = Elasticsearch + Logstash + Kibana — très utilisé en entreprise.
1. Concepts fondamentaux
Vocabulaire
| SQL | Elasticsearch | Description |
|---|---|---|
| Database | Cluster | Ensemble de nœuds |
| Table | Index | Collection de documents |
| Row | Document | Une entrée (JSON) |
| Column | Field | Un champ du document |
| Schema | Mapping | Structure des champs |
État du cluster
| État | Signification |
|---|---|
| 🟢 Green | Tous les shards OK |
| 🟡 Yellow | Primaires OK, replicas non alloués (1 seul nœud) |
| 🔴 Red | Données inaccessibles |
2. Installation
Étape 1 : Télécharger Elasticsearch
👉 https://www.elastic.co/downloads/elasticsearch
- Télécharger le ZIP pour ton OS
- Dézipper dans un dossier (ex:
C:\elasticsearch) - Modifier
config/elasticsearch.yml:
# Désactiver la sécurité pour les tests
xpack.security.enabled: false- Lancer Elasticsearch :
# Windows
.\bin\elasticsearch.bat
# macOS / Linux
./bin/elasticsearch- Vérifier : ouvrir http://localhost:9200 dans le navigateur
Étape 2 : Installer Elasticvue
Elasticvue est une interface graphique pour Elasticsearch — beaucoup plus simple que les commandes curl !
Options d’installation :
| Option | Lien |
|---|---|
| App Web (recommandé) | https://app.elasticvue.com |
| Extension Chrome | Chrome Web Store |
| Extension Firefox | Firefox Add-ons |
| App Desktop | elasticvue.com |
3. Guide Elasticvue — Prise en main
3.1 Connexion au cluster
- Ouvrir Elasticvue
- Cliquer sur “Add Cluster”
- Remplir :
- Name :
Local(ou ce que tu veux) - URI :
http://localhost:9200
- Name :
- Cliquer “Connect”
✅ Tu devrais voir le statut du cluster (🟢 Green ou 🟡 Yellow)
3.2 Interface principale
┌─────────────────────────────────────────────────────────────┐
│ Elasticvue [Cluster: Local] │
├─────────────┬───────────────────────────────────────────────┤
│ │ │
│ Home │ Cluster Health: 🟢 Green │
│ │ Nodes: 1 │
│ Indices │ Indices: 3 │
│ │ Documents: 1,234 │
│ Search │ │
│ │ │
│ REST │ ◄── C'est ici qu'on écrit les requêtes ! │
│ │ │
│ Settings│ │
│ │ │
└─────────────┴───────────────────────────────────────────────┘
Onglets importants :
| Onglet | Usage |
|---|---|
| Indices | Voir/créer/supprimer des index |
| Search | Rechercher visuellement dans un index |
| REST | Écrire des requêtes (comme Kibana Dev Tools) |
3.3 Utiliser la console REST
L’onglet REST permet d’exécuter des requêtes Elasticsearch avec une syntaxe simple.
Format des requêtes
MÉTHODE /chemin
{
"corps": "de la requête en JSON"
}
Exemple pas à pas
┌──────────────────────────────────────────────────────────────┐
│ REST Query [▶ Run] │
├──────────────────────────────────────────────────────────────┤
│ │
│ GET /clients/_search │
│ { │
│ "query": { │
│ "match": { "pays": "France" } │
│ } │
│ } │
│ │
├──────────────────────────────────────────────────────────────┤
│ Response (200 OK) │
│ { │
│ "hits": { │
│ "total": { "value": 2 }, │
│ "hits": [...] │
│ } │
│ } │
└──────────────────────────────────────────────────────────────┘
Raccourcis utiles
| Raccourci | Action |
|---|---|
Ctrl + Enter |
Exécuter la requête |
Ctrl + / |
Commenter une ligne |
Ctrl + Space |
Autocomplétion |
4. Créer un index et insérer des données
4.1 Créer l’index clients
Dans l’onglet REST, copier-coller :
PUT /clients
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"nom": { "type": "text" },
"email": { "type": "keyword" },
"pays": { "type": "keyword" },
"age": { "type": "integer" },
"salaire": { "type": "float" }
}
}
}
✅ Réponse attendue : { "acknowledged": true }
4.2 Comprendre le mapping
| Type | Usage | Recherche full-text | Agrégation |
|---|---|---|---|
text |
Texte analysé | ✅ Oui | ❌ Non |
keyword |
Valeur exacte | ❌ Non | ✅ Oui |
integer, float |
Nombres | Range ✅ | ✅ Oui |
date |
Dates | Range ✅ | ✅ Oui |
boolean |
true/false | ✅ | ✅ Oui |
💡 Règle : Utilise
keywordpour les champs sur lesquels tu veux faire des agrégations (GROUP BY).
Index Templates — Automatiser les mappings
Pourquoi utiliser des templates ?
Quand tu gères des logs ou des données temporelles, tu crées souvent des index par jour ou par mois :
logs-2024-01-01
logs-2024-01-02
logs-2024-01-03
...
Problème : Sans template, chaque index utilise le mapping dynamique (Elasticsearch devine les types). C’est risqué !
Solution : Créer un Index Template qui s’applique automatiquement à tous les index correspondant à un pattern.
Créer un Index Template
PUT /_index_template/logs_template
{
"index_patterns": ["logs-*"],
"priority": 1,
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" },
"service": { "type": "keyword" },
"host": { "type": "keyword" },
"response_time_ms": { "type": "integer" }
}
}
}
}
Maintenant, tout index créé avec le pattern logs-* aura automatiquement ce mapping !
Tester le template
# Créer un index qui match le pattern
POST /logs-2024-01-15/_doc
{
"timestamp": "2024-01-15T10:30:00Z",
"level": "ERROR",
"message": "Connection timeout to database",
"service": "api-gateway",
"host": "server-01",
"response_time_ms": 5000
}
# Vérifier que le mapping a été appliqué
GET /logs-2024-01-15/_mapping
Lister les templates existants
GET /_index_template
Supprimer un template
DELETE /_index_template/logs_template
💡 Bonnes pratiques Index Templates
| Pratique | Explication |
|---|---|
| Toujours définir un mapping | Ne pas laisser ES deviner les types |
Utiliser keyword pour les agrégations |
level, service, host → keyword |
Utiliser text pour la recherche |
message → text |
Définir date explicitement |
Évite les erreurs de parsing |
| Nommer clairement | logs_template, metrics_template |
Utiliser priority |
Quand plusieurs templates matchent |
4.3 Insérer un document
POST /clients/_doc
{
"nom": "Alice Dupont",
"email": "alice@email.com",
"pays": "France",
"age": 30,
"salaire": 55000
}
4.4 Insérer plusieurs documents (Bulk)
POST /_bulk
{ "index": { "_index": "clients" } }
{ "nom": "Bob Martin", "email": "bob@email.com", "pays": "France", "age": 25, "salaire": 48000 }
{ "index": { "_index": "clients" } }
{ "nom": "Charlie Konan", "email": "charlie@email.com", "pays": "Côte d'Ivoire", "age": 35, "salaire": 62000 }
{ "index": { "_index": "clients" } }
{ "nom": "Diana Schmidt", "email": "diana@email.com", "pays": "Allemagne", "age": 28, "salaire": 51000 }
{ "index": { "_index": "clients" } }
{ "nom": "Eve Kouassi", "email": "eve@email.com", "pays": "Côte d'Ivoire", "age": 32, "salaire": 58000 }
⚠️ Attention : En bulk, chaque ligne doit être sur une seule ligne (pas de formatage JSON multi-lignes).
5. Requêtes de recherche
5.1 Afficher tous les documents
GET /clients/_search
✅ SQL équivalent : SELECT * FROM clients
5.2 Filtrer avec match (full-text)
GET /clients/_search
{
"query": {
"match": { "nom": "Alice" }
}
}
✅ SQL équivalent : SELECT * FROM clients WHERE nom LIKE '%Alice%'
5.3 Filtrer avec term (exact match)
GET /clients/_search
{
"query": {
"term": { "pays": "France" }
}
}
✅ SQL équivalent : SELECT * FROM clients WHERE pays = 'France'
💡 Utilise
termpour les champskeyword,matchpour les champstext.
5.4 Filtrer par plage de valeurs (range)
GET /clients/_search
{
"query": {
"range": {
"age": {
"gte": 25,
"lte": 35
}
}
}
}
✅ SQL équivalent : SELECT * FROM clients WHERE age BETWEEN 25 AND 35
| Opérateur | Signification |
|---|---|
gt |
> (greater than) |
gte |
>= (greater than or equal) |
lt |
< (less than) |
lte |
<= (less than or equal) |
5.5 Conditions multiples (bool)
La requête bool combine plusieurs conditions :
| Clause | Comportement | SQL équivalent |
|---|---|---|
must |
Toutes les conditions requises | AND |
should |
Au moins une condition | OR |
must_not |
Exclure | NOT / != |
filter |
Comme must mais sans score |
WHERE (optimisé) |
Exemple : Clients français de plus de 25 ans
GET /clients/_search
{
"query": {
"bool": {
"must": [
{ "term": { "pays": "France" } },
{ "range": { "age": { "gt": 25 } } }
]
}
}
}
✅ SQL équivalent : SELECT * FROM clients WHERE pays = 'France' AND age > 25
Exemple : Clients français OU ivoiriens, mais PAS Bob
GET /clients/_search
{
"query": {
"bool": {
"should": [
{ "term": { "pays": "France" } },
{ "term": { "pays": "Côte d'Ivoire" } }
],
"minimum_should_match": 1,
"must_not": [
{ "match": { "nom": "Bob" } }
]
}
}
}
✅ SQL équivalent : SELECT * FROM clients WHERE (pays = 'France' OR pays = 'Côte d''Ivoire') AND nom != 'Bob'
5.6 Recherche floue (fuzzy)
Trouve des résultats même avec des fautes de frappe :
GET /clients/_search
{
"query": {
"fuzzy": {
"nom": {
"value": "Alise",
"fuzziness": "AUTO"
}
}
}
}
✅ Trouve “Alice” même si on tape “Alise” !
💡 Pas d’équivalent simple en SQL — c’est la force d’Elasticsearch.
📌 5.7 Trier et limiter les résultats
GET /clients/_search
{
"query": { "match_all": {} },
"sort": [
{ "salaire": "desc" }
],
"size": 3
}
✅ SQL équivalent : SELECT * FROM clients ORDER BY salaire DESC LIMIT 3
6. Agrégations (GROUP BY)
6.1 Compter par catégorie (terms)
GET /clients/_search
{
"size": 0,
"aggs": {
"par_pays": {
"terms": { "field": "pays" }
}
}
}
✅ SQL équivalent : SELECT pays, COUNT(*) FROM clients GROUP BY pays
💡
size: 0= ne pas retourner les documents, seulement l’agrégation.
6.2 Métriques (sum, avg, min, max)
GET /clients/_search
{
"size": 0,
"aggs": {
"salaire_moyen": { "avg": { "field": "salaire" } },
"salaire_max": { "max": { "field": "salaire" } },
"salaire_min": { "min": { "field": "salaire" } },
"salaire_total": { "sum": { "field": "salaire" } }
}
}
✅ SQL équivalent : SELECT AVG(salaire), MAX(salaire), MIN(salaire), SUM(salaire) FROM clients
6.3 Stats complètes en une requête
GET /clients/_search
{
"size": 0,
"aggs": {
"stats_salaire": {
"stats": { "field": "salaire" }
}
}
}
Résultat : count, min, max, avg, sum en une seule requête !
6.4 Agrégations imbriquées (GROUP BY + métriques)
GET /clients/_search
{
"size": 0,
"aggs": {
"par_pays": {
"terms": { "field": "pays" },
"aggs": {
"salaire_moyen": { "avg": { "field": "salaire" } },
"age_moyen": { "avg": { "field": "age" } }
}
}
}
}
✅ SQL équivalent :
SELECT pays, AVG(salaire) AS salaire_moyen, AVG(age) AS age_moyen
FROM clients
GROUP BY pays;6.5 Filtrer avant d’agréger
GET /clients/_search
{
"size": 0,
"query": {
"range": { "salaire": { "gte": 50000 } }
},
"aggs": {
"par_pays": {
"terms": { "field": "pays" }
}
}
}
✅ SQL équivalent :
SELECT pays, COUNT(*)
FROM clients
WHERE salaire >= 50000
GROUP BY pays;7. Modifier et supprimer
7.1 Mettre à jour un document (par ID)
POST /clients/_update/1
{
"doc": {
"salaire": 60000
}
}
7.2 Mettre à jour par requête
POST /clients/_update_by_query
{
"query": {
"term": { "pays": "France" }
},
"script": {
"source": "ctx._source.salaire += 1000"
}
}
✅ SQL équivalent : UPDATE clients SET salaire = salaire + 1000 WHERE pays = 'France'
7.3 Supprimer un document (par ID)
DELETE /clients/_doc/1
7.4 Supprimer par requête
POST /clients/_delete_by_query
{
"query": {
"range": { "age": { "lt": 18 } }
}
}
✅ SQL équivalent : DELETE FROM clients WHERE age < 18
7.5 Supprimer un index entier
DELETE /clients
⚠️ Attention : Irréversible !
Cheatsheet Elasticsearch
Gestion des index
| Action | Requête |
|---|---|
| Créer un index | PUT /mon_index |
| Supprimer | DELETE /mon_index |
| Lister | GET /_cat/indices?v |
| Voir mapping | GET /mon_index/_mapping |
| Santé cluster | GET /_cluster/health |
CRUD Documents
| Action | Requête |
|---|---|
| Insérer | POST /index/_doc |
| Lire (ID) | GET /index/_doc/1 |
| Mettre à jour | POST /index/_update/1 |
| Supprimer | DELETE /index/_doc/1 |
| Bulk | POST /_bulk |
Types de requêtes
| Type | Usage |
|---|---|
match |
Full-text (champs text) |
term |
Exact (champs keyword) |
range |
Plage (nombres, dates) |
bool |
Combiner (must, should, must_not) |
fuzzy |
Tolérant aux fautes |
Agrégations
| Type | SQL équivalent |
|---|---|
terms |
GROUP BY |
sum, avg, min, max |
Fonctions d’agrégation |
stats |
Toutes les stats |
cardinality |
COUNT(DISTINCT) |
Exercices pratiques
Utilise l’onglet REST d’Elasticvue pour résoudre ces exercices.
Exercice 1 — Facile
Afficher tous les clients.
💡 Solution
GET /clients/_search
Exercice 2 — Facile
Trouver les clients de Côte d’Ivoire.
💡 Solution
GET /clients/_search
{
"query": {
"term": { "pays": "Côte d'Ivoire" }
}
}
Exercice 3 — Intermédiaire
Trouver les clients avec un salaire entre 50000 et 60000, triés par âge décroissant.
💡 Solution
GET /clients/_search
{
"query": {
"range": {
"salaire": { "gte": 50000, "lte": 60000 }
}
},
"sort": [{ "age": "desc" }]
}
Exercice 4 — Intermédiaire
Calculer le nombre de clients par pays.
💡 Solution
GET /clients/_search
{
"size": 0,
"aggs": {
"par_pays": {
"terms": { "field": "pays" }
}
}
}
Exercice 5 — Avancé
Calculer le salaire moyen par pays, seulement pour les clients de plus de 25 ans.
💡 Solution
GET /clients/_search
{
"size": 0,
"query": {
"range": { "age": { "gt": 25 } }
},
"aggs": {
"par_pays": {
"terms": { "field": "pays" },
"aggs": {
"salaire_moyen": { "avg": { "field": "salaire" } }
}
}
}
}
Quiz
❓ Q1. Quelle requête crée un index ?
POST /clients
PUT /clients
GET /clients
CREATE /clients
💡 Réponse
✅ b —PUT /index crée un nouvel index.
❓ Q2. Quelle est la différence entre text et keyword ?
- Aucune différence
textest analysé (tokenisé),keywordest stocké tel quel
keywordest plus rapide
textest pour les nombres
💡 Réponse
✅ b —text est découpé en tokens pour la recherche full-text, keyword reste intact pour les matchs exacts et agrégations.
❓ Q3. Quelle requête utiliser pour un GROUP BY ?
match
bool
terms(dans aggs)
range
💡 Réponse
✅ c — L’agrégationterms groupe les documents par valeur de champ.
❓ Q4. Que fait size: 0 dans une requête d’agrégation ?
- Supprime les données
- Retourne uniquement l’agrégation, pas les documents
- Limite à 0 résultat d’agrégation
- Erreur
💡 Réponse
✅ b —size: 0 évite de retourner les documents, seulement les résultats d’agrégation.
❓ Q5. Quelle requête permet de chercher “Alice” même si on tape “Alise” ?
match
term
fuzzy
range
💡 Réponse
✅ c —fuzzy tolère les fautes de frappe.
📚 Ressources
- Elasticsearch Documentation
- Elasticvue — Interface graphique utilisée dans ce cours
- Kibana — Visualisation et dashboards
- Elastic Cloud — Version cloud managée
➡️ Prochaine étape
Tu maîtrises maintenant les bases NoSQL (MongoDB et Elasticsearch) ! Passons au traitement distribué avec PySpark.
👉 Module suivant : 11_pyspark_for_data_engineering — PySpark pour le traitement Big Data
🎉 Félicitations ! Tu as terminé le module Elasticsearch pour Data Engineers.