Fiche de rappel d'Elasticsearch : commandes et astuces essentielles

Commandes Elasticsearch pour la recherche, l'indexation et l'analyse

Sommaire

Elasticsearch est un moteur de recherche et d’analyse distribué puissant construit sur Apache Lucene. Ce guide complet couvre les commandes essentielles, les bonnes pratiques et les références rapides pour travailler avec des clusters Elasticsearch.

elasticsearch

Note : La plupart des exemples de ce guide utilisent cURL pour les requêtes HTTP. Si vous débutez avec cURL ou si vous avez besoin d’une référence rapide pour les options avancées, consultez notre cURL Cheatsheet pour des techniques détaillées de requêtes HTTP en ligne de commande.

Gestion des clusters

Vérifier l’état du cluster

Toutes les commandes de cette section utilisent cURL pour interagir avec l’API REST d’Elasticsearch. Vous pouvez personnaliser ces requêtes avec des en-têtes supplémentaires, une authentification et d’autres options si nécessaire.

# Vérification de base
curl -X GET "localhost:9200/_cluster/health?pretty"

# État détaillé du cluster avec des informations sur les fragments
curl -X GET "localhost:9200/_cluster/health?level=shards&pretty"

# Vérifier les informations sur les nœuds
curl -X GET "localhost:9200/_cat/nodes?v"

# Vérifier les paramètres du cluster
curl -X GET "localhost:9200/_cluster/settings?pretty"

Opérations sur les nœuds

# Liste de tous les nœuds
curl -X GET "localhost:9200/_cat/nodes?v&h=name,node.role,heap.percent,ram.percent,cpu,load_1m"

# Statistiques des nœuds
curl -X GET "localhost:9200/_nodes/stats?pretty"

# Threads chauds (débogage)
curl -X GET "localhost:9200/_nodes/hot_threads"

Gestion des index

Créer et supprimer des index

# Créer un index
curl -X PUT "localhost:9200/my_index?pretty"

# Créer un index avec des paramètres
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}
'

# Supprimer un index
curl -X DELETE "localhost:9200/my_index?pretty"

# Liste de tous les index
curl -X GET "localhost:9200/_cat/indices?v"

# Statistiques de l'index
curl -X GET "localhost:9200/my_index/_stats?pretty"

Mappages d’index

# Définir un mappage
curl -X PUT "localhost:9200/products" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "price": { "type": "float" },
      "created_at": { "type": "date" },
      "tags": { "type": "keyword" },
      "description": { 
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}
'

# Obtenir le mappage
curl -X GET "localhost:9200/products/_mapping?pretty"

# Mettre à jour le mappage (ajouter un champ)
curl -X PUT "localhost:9200/products/_mapping" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "category": { "type": "keyword" }
  }
}
'

Modèles d’index

# Créer un modèle d'index
curl -X PUT "localhost:9200/_index_template/logs_template" -H 'Content-Type: application/json' -d'
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 1
    },
    "mappings": {
      "properties": {
        "timestamp": { "type": "date" },
        "message": { "type": "text" },
        "level": { "type": "keyword" }
      }
    }
  }
}
'

# Liste des modèles
curl -X GET "localhost:9200/_index_template?pretty"

Opérations sur les documents (CRUD)

Créer des documents

# Indexer un document avec un ID généré automatiquement
curl -X POST "localhost:9200/products/_doc?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99,
  "tags": ["electronics", "computers"]
}
'

# Indexer un document avec un ID spécifique
curl -X PUT "localhost:9200/products/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99
}
'

# Indexation en masse
curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index": { "_index": "products", "_id": "1" }}
{ "name": "Laptop", "price": 999.99 }
{ "index": { "_index": "products", "_id": "2" }}
{ "name": "Mouse", "price": 29.99 }
'

Lire des documents

# Obtenir un document par ID
curl -X GET "localhost:9200/products/_doc/1?pretty"

# Obtenir plusieurs documents
curl -X GET "localhost:9200/_mget?pretty" -H 'Content-Type: application/json' -d'
{
  "docs": [
    { "_index": "products", "_id": "1" },
    { "_index": "products", "_id": "2" }
  ]
}
'

# Vérifier si un document existe
curl -I "localhost:9200/products/_doc/1"

Mettre à jour des documents

# Mettre à jour un document
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  }
}
'

# Mettre à jour avec un script
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "script": {
    "source": "ctx._source.price *= params.discount",
    "params": {
      "discount": 0.9
    }
  }
}
'

# Mettre à jour ou insérer (upsert)
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  },
  "doc_as_upsert": true
}
'

Supprimer des documents

# Supprimer par ID
curl -X DELETE "localhost:9200/products/_doc/1?pretty"

# Supprimer par requête
curl -X POST "localhost:9200/products/_delete_by_query?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "old"
    }
  }
}
'

Requêtes de recherche

Recherche de base

# Correspondre à tout
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'

# Requête de correspondance
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "laptop"
    }
  }
}
'

# Requête multi-correspondance
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "laptop gaming",
      "fields": ["name", "description"]
    }
  }
}
'

Requêtes de niveau terme

# Requête terme (correspondance exacte)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "tags": "electronics"
    }
  }
}
'

# Requête termes (plusieurs valeurs)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "terms": {
      "tags": ["electronics", "computers"]
    }
  }
}
'

# Requête de plage
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 1000
      }
    }
  }
}
'

# Requête d'existence
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "exists": {
      "field": "description"
    }
  }
}
'

Requêtes booléennes

# Requête booléenne (doit, devrait, ne doit pas, filtre)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "laptop" }}
      ],
      "filter": [
        { "range": { "price": { "gte": 500 }}}
      ],
      "should": [
        { "term": { "tags": "gaming" }}
      ],
      "must_not": [
        { "term": { "tags": "refurbished" }}
      ]
    }
  }
}
'

Recherche avancée

# Requête sauvage
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "wildcard": {
      "name": "lap*"
    }
  }
}
'

# Requête floue (tolérance aux fautes de frappe)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "laptpo",
        "fuzziness": "AUTO"
      }
    }
  }
}
'

# Requête préfixe
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "prefix": {
      "name": "lap"
    }
  }
}
'

Agrégations

Agrégations de métrique

# Moyenne, somme, minimum, maximum
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "avg_price": { "avg": { "field": "price" }},
    "max_price": { "max": { "field": "price" }},
    "min_price": { "min": { "field": "price" }},
    "total_sales": { "sum": { "field": "price" }}
  }
}
'

# Agrégation de statistiques
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_stats": {
      "stats": { "field": "price" }
    }
  }
}
'

Agrégations de bucket

# Agrégation de termes (grouper par)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "popular_tags": {
      "terms": {
        "field": "tags",
        "size": 10
      }
    }
  }
}
'

# Agrégation de plage
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 50 },
          { "from": 50, "to": 100 },
          { "from": 100 }
        ]
      }
    }
  }
}
'

# Histogramme de date
curl -X GET "localhost:9200/logs/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "logs_over_time": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      }
    }
  }
}
'

Agrégations imbriquées

# Agrégations imbriquées
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "categories": {
      "terms": { "field": "category" },
      "aggs": {
        "avg_price": {
          "avg": { "field": "price" }
        }
      }
    }
  }
}
'

Tri et pagination

# Tri par champ
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "price": { "order": "desc" }},
    { "_score": { "order": "desc" }}
  ]
}
'

# Pagination avec from/size
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "from": 0,
  "size": 10,
  "query": { "match_all": {} }
}
'

# Recherche après (pour la pagination profonde)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 10,
  "query": { "match_all": {} },
  "sort": [{ "price": "asc" }, { "_id": "asc" }],
  "search_after": [100, "product_123"]
}
'

Sélection de champs et mise en évidence

# Sélectionner des champs spécifiques
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}
'

# Mise en évidence
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": { "description": "gaming laptop" }
  },
  "highlight": {
    "fields": {
      "description": {}
    }
  }
}
'

Aliases d’index

# Créer un alias
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "add": { "index": "products_v1", "alias": "products" }}
  ]
}
'

# Changer d'alias vers un nouvel index (sans temps d'arrêt)
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "remove": { "index": "products_v1", "alias": "products" }},
    { "add": { "index": "products_v2", "alias": "products" }}
  ]
}
'

# Liste des aliases
curl -X GET "localhost:9200/_cat/aliases?v"

Réindexation

# Réindexer d'un index à un autre
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "old_products"
  },
  "dest": {
    "index": "new_products"
  }
}
'

# Réindexer avec une requête
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "products",
    "query": {
      "range": {
        "price": { "gte": 100 }
      }
    }
  },
  "dest": {
    "index": "expensive_products"
  }
}
'

Sauvegardes et sauvegardes instantanées

# Enregistrer un dépôt de sauvegarde
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/mount/backups/my_backup"
  }
}
'

# Créer une sauvegarde
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true&pretty"

# Restaurer une sauvegarde
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore?pretty"

# Liste des sauvegardes
curl -X GET "localhost:9200/_snapshot/my_backup/_all?pretty"

# Supprimer une sauvegarde
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_1?pretty"

Optimisation des performances

Paramètres d’index

# Désactiver le rafraîchissement pendant l'indexation en masse
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "-1"
  }
}
'

# Réactiver après l'indexation en masse
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "1s"
  }
}
'

# Fusion de segments (optimisation)
curl -X POST "localhost:9200/products/_forcemerge?max_num_segments=1&pretty"

Nettoyage du cache

# Nettoyer tous les caches
curl -X POST "localhost:9200/_cache/clear?pretty"

# Nettoyer un cache spécifique
curl -X POST "localhost:9200/products/_cache/clear?query=true&pretty"

Surveillance et dépannage

# Tâches en attente
curl -X GET "localhost:9200/_cat/pending_tasks?v"

# Statistiques du pool de threads
curl -X GET "localhost:9200/_cat/thread_pool?v"

# Informations sur les segments
curl -X GET "localhost:9200/_cat/segments?v"

# Informations de récupération
curl -X GET "localhost:9200/_cat/recovery?v&h=index,stage,time"

# API des tâches
curl -X GET "localhost:9200/_tasks?detailed=true&pretty"

Exemples de client Python

from elasticsearch import Elasticsearch

# Se connecter à Elasticsearch
es = Elasticsearch(['http://localhost:9200'])

# Indexer un document
doc = {
    'name': 'Laptop',
    'price': 999.99,
    'tags': ['electronics']
}
es.index(index='products', id=1, document=doc)

# Recherche
resp = es.search(index='products', query={'match': {'name': 'laptop'}})
for hit in resp['hits']['hits']:
    print(hit['_source'])

# Indexation en masse
from elasticsearch.helpers import bulk

actions = [
    {
        '_index': 'products',
        '_id': i,
        '_source': {'name': f'Product {i}', 'price': i * 10}
    }
    for i in range(1000)
]
bulk(es, actions)

Exemples de client JavaScript/Node.js

Le client JavaScript d’Elasticsearch fournit une manière type-safe d’interagir avec votre cluster. Pour les applications en production, envisagez d’utiliser TypeScript pour une meilleure sécurité de type et une complétion d’auto. Consultez notre TypeScript Cheatsheet pour les bonnes pratiques sur les définitions de type et les interfaces.

const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });

// Indexer un document
async function indexDoc() {
  await client.index({
    index: 'products',
    id: 1,
    document: {
      name: 'Laptop',
      price: 999.99
    }
  });
}

// Recherche
async function search() {
  const result = await client.search({
    index: 'products',
    query: {
      match: { name: 'laptop' }
    }
  });
  console.log(result.hits.hits);
}

// Indexation en masse
async function bulkIndex() {
  const operations = [];
  for (let i = 0; i < 1000; i++) {
    operations.push({ index: { _index: 'products', _id: i } });
    operations.push({ name: `Product ${i}`, price: i * 10 });
  }
  await client.bulk({ operations });
}

Exemple TypeScript avec typage fort

import { Client } from '@elastic/elasticsearch';

interface Product {
  name: string;
  price: number;
  tags?: string[];
  created_at?: Date;
}

const client = new Client({ node: 'http://localhost:9200' });

async function indexProduct(product: Product, id: number): Promise<void> {
  await client.index<Product>({
    index: 'products',
    id: id.toString(),
    document: product
  });
}

async function searchProducts(query: string): Promise<Product[]> {
  const result = await client.search<Product>({
    index: 'products',
    query: {
      match: { name: query }
    }
  });
  
  return result.hits.hits.map(hit => hit._source as Product);
}

Bonnes pratiques

Conception d’index

  • Gardez la taille des fragments entre 20 et 50 Go pour une performance optimale
  • Utilisez la gestion du cycle de vie des index (ILM) pour les données chronologiques
  • Concevez soigneusement les mappages avant d’indexer les données
  • Utilisez les types de champ appropriés (keyword vs text, formats de date)
  • Désactivez _source pour les documents volumineux si cela n’est pas nécessaire

Optimisation des requêtes

  • Utilisez des filtres plutôt que des requêtes lorsque le classement n’est pas nécessaire
  • Privilégiez les requêtes de niveau terme pour les données structurées
  • Utilisez la requête bool pour combiner efficacement plusieurs conditions
  • Implémentez la pagination avec search_after pour la pagination profonde
  • Cachez les filtres fréquemment utilisés

Performance d’indexation

  • Utilisez l’API bulk pour l’indexation en lots (1000 à 5000 documents par requête)
  • Désactivez le rafraîchissement pendant les opérations d’indexation
  • Augmentez index.refresh_interval pendant les indexations lourdes
  • Utilisez plusieurs threads/ouvriers pour l’indexation parallèle
  • Considérez l’utilisation du routage pour une meilleure distribution des fragments

Gestion du cluster

  • Surveillez régulièrement l’état du cluster
  • Configurez correctement le nombre de réplicas
  • Utilisez des nœuds maîtres dédiés pour les grands clusters
  • Implémentez une stratégie de sauvegarde appropriée avec des sauvegardes
  • Surveillez l’utilisation de la mémoire JVM (gardez-la en dessous de 75 %)

Sécurité

  • Activez l’authentification et l’autorisation (X-Pack Security)
  • Utilisez HTTPS pour les déploiements en production (configurez cURL avec --cacert, --cert et --key pour SSL/TLS)
  • Implémentez une gestion des rôles appropriée
  • Mises à jour et correctifs de sécurité réguliers
  • Chiffrez les données au repos et en transit

Cas d’utilisation courants

Recherche en texte intégral

Elasticsearch excelle dans la recherche en texte intégral grâce à des fonctionnalités comme :

  • Classement de pertinence
  • Correspondance floue
  • Correspondance de phrase
  • Gestion des synonymes
  • Support multilingue

Analyse de logs (pile ELK)

  • Collecter les logs avec Logstash/Filebeat
  • Indexer et rechercher les logs dans Elasticsearch
  • Visualiser avec des tableaux de bord Kibana
  • Configurer des alertes pour les anomalies

Recherche e-commerce

  • Recherche de catalogue de produits
  • Navigation facettée avec des agrégations
  • Suggestions et complétions automatiques
  • Résultats de recherche personnalisés

Surveillance des performances des applications

  • Indexer les métriques des applications
  • Tableaux de bord de surveillance en temps réel
  • Détection d’anomalies
  • Analyse des tendances de performance

Liens utiles

Ressources officielles d’Elasticsearch

Cheatsheets et guides connexes