Atelier fondamental 1 — Elasticsearch : un index, un document, une requête GET

Pratique guidée40 min
Durée
45 min
Module
1/7
Prérequis
le labo tourne (etat affiche (healthy) partout), Kibana Dev Tools ouvert
Tu vas construire
un index à toi, pratique-mini, avec deux documents que tu vas lire, compléter, chercher puis supprimer
Livrable
la réponse de GET pratique-mini/_doc/1 après l'étape 5, avec ses trois champs

Comment lire cette page. D'abord trois parties à taper dans l'ordre : les commandes, puis la question qui les concerne. Ouvre « Pour bien comprendre » si une commande n'est pas claire. Les réponses sont repliées juste avant les huit étapes : réponds avant de les ouvrir. Ensuite on révise les étapes en gros, puis tu les refais une par une : le titre reste visible, le détail s'ouvre au clic. Tape toi-même chaque requête (pas de copier-coller) : c'est en écrivant PUT, GET, _doc que les mots rentrent. Si le labo n'est pas démarré, retourne à la pratique guidée : la section En bref donne les commandes, kit compris (https://github.com/hrhouma2/aiopsatlas-recherche-graphes-labo-fr).

Objectif

La pratique guidée t'a fait charger 504 cours, 609 avis et 12 000 lignes de journal d'un coup, avec un script. Tu as vu les chiffres, mais tu n'as encore rien écrit toi-même. Ici, tu repars de zéro : un index vide que tu crées, une première fiche que tu ranges dedans, que tu relis, que tu complètes, puis une deuxième, une recherche, une suppression. À la fin, tu sais ce qu'est un index et un document parce que tu en as fabriqué un, pas parce qu'on te l'a dit.

Le vocabulaire en une image

Un index est une armoire. Un document est une fiche rangée dans l'armoire : un petit texte JSON avec des champs. Chaque fiche a un numéro, son _id, qui permet de la retrouver directement sans chercher. Tu n'as pas à déclarer les colonnes à l'avance : la première fiche rangée crée le mapping (le plan de l'armoire) toute seule.

ElasticsearchBase SQL classiqueDans cette pratique
indextablepratique-mini
documentligne{"titre": "Mon premier document"}
champcolonnetitre, auteur, note
_idclé primaire1, 2
mappingschéma de la table (CREATE TABLE …)créé automatiquement à l'étape 3
_sourcela ligne telle que tu l'as écritece que GET _doc/1 te rend

Où taper, et comment lire une requête

Ouvre http://localhost:5601, menu ☰ → ManagementDev Tools. Le panneau de gauche reçoit les requêtes, celui de droite affiche la réponse. Tu envoies avec Ctrl + Entrée (Cmd + Entrée sur macOS) ou le bouton ▶ à droite de la ligne.

Toute requête a la même forme : un verbe, un chemin, et parfois un corps JSON en dessous.

VerbeCe qu'il faitÉquivalent SQL
GETlire, sans rien changerSELECT
PUTcréer, ou remplacer entièrementCREATE TABLE, INSERT (ou remplacer la ligne)
POSTagir : mettre à jour, chercher avec un corpsUPDATE
DELETEsupprimerDROP TABLE, DELETE

Le chemin dit sur quoi on agit : pratique-mini (l'armoire), pratique-mini/_doc/1 (la fiche numéro 1 de l'armoire), pratique-mini/_search (chercher dans l'armoire). Les mots qui commencent par _ sont des commandes d'Elasticsearch, pas des noms à toi.

Avant les huit étapes

Trois parties, dans cet ordre. Tape chaque commande, lis la réponse à droite, puis réponds à la question. Les réponses sont plus bas, juste avant l'étape 1.

Partie 1 — Différence entre PUT et POST

text
PUT pratique-mini
text
GET _cat/indices/pratique-mini?v
text
PUT pratique-mini/_doc/1
{
  "titre": "Introduction à Docker",
  "categorie": "DevOps",
  "niveau": "débutant"
}
text
POST pratique-mini/_doc
{
  "titre": "Introduction à Kubernetes",
  "categorie": "Cloud",
  "niveau": "intermédiaire"
}
text
PUT pratique-mini/_doc/3
{
  "titre": "Introduction aux LLMs",
  "categorie": "IA",
  "niveau": "intermédiaire"
}

Question 1. Quelle est la différence entre PUT et POST ?

Indice : GET pratique-mini/_search, et regarde le champ _id de chaque fiche.

Question 2. Peut-on modifier la structure en ajoutant un champ nouveau, par exemple langue, à un document ?

Pour le voir, tape :

text
POST pratique-mini/_doc/5
{
  "titre": "Introduction à Kubernetes",
  "categorie": "Cloud",
  "niveau": "intermédiaire",
  "langue": "fr"
}

Question 3. Comment déclarer précisément les champs autorisés et leur type, pour refuser une donnée qui ne respecte pas le plan ?

text
PUT pratique-mini-strict
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "titre": { "type": "text" },
      "categorie": { "type": "keyword" },
      "niveau": { "type": "keyword" },
      "langue": { "type": "keyword" }
    }
  }
}
text
PUT pratique-mini-strict/_doc/5
{
  "titre": "Introduction à Kubernetes",
  "categorie": "Cloud",
  "niveau": "intermédiaire",
  "langue": "fr"
}
text
PUT pratique-mini-strict/_doc/6
{
  "titre": "Introduction à Docker",
  "categorie": "DevOps",
  "niveau": "débutant",
  "langue": "fr",
  "prix": 100
}

Cette dernière requête est refusée. Lis le message.

Question 4. Dans quels cas concrets utilise-t-on un mapping strict ?

Pour bien comprendre : lire les commandes de la partie 1
  • PUT pratique-mini, sans corps. Tu crées l'armoire et rien d'autre : pas de champs, pas de fiche. Le nom est en minuscules. pratique- devant permet, plus tard, de lister uniquement tes index avec pratique-*.
  • GET _cat/indices/pratique-mini?v. Une seule ligne de résumé. ?v (verbose) affiche les noms de colonnes. Tu y lis health (la couleur), status (open : on peut écrire), docs.count (le nombre de fiches), rep (le nombre de copies demandées en plus de l'original).
  • PUT pratique-mini/_doc/1. _doc veut dire « une fiche ». Le 1 est dans le chemin : c'est toi qui choisis le numéro, le _id. Le corps JSON est la fiche : titre, categorie, niveau.
  • POST pratique-mini/_doc. Le chemin s'arrête à _doc. Il n'y a pas de numéro. Le corps a la même forme que la fiche 1, avec d'autres valeurs.
  • PUT pratique-mini/_doc/3. Encore un numéro choisi, le 3. Personne n'a créé la fiche 2 : les numéros ne se suivent pas tout seuls.
  • POST pratique-mini/_doc/5 ajoute le champ langue. La fiche a un champ de plus que les précédentes. Par défaut, Elasticsearch accepte ce champ et l'ajoute au mapping (le plan de l'armoire) sans que tu aies à le déclarer. C'est le mapping dynamique.
  • PUT pratique-mini-strict avec mappings. Cette fois le corps décrit le plan avant toute fiche. "dynamic": "strict" veut dire : refuse tout champ qui n'est pas dans properties. text sert à chercher des mots (titre). keyword sert à une valeur exacte (categorie, niveau, langue).
  • PUT pratique-mini-strict/_doc/5 n'envoie que des champs déclarés. PUT pratique-mini-strict/_doc/6 ajoute prix, qui n'est pas dans properties. Lis le message d'erreur : il nomme le champ refusé.

Partie 2 — Vert, jaune, rouge

text
PUT pratique-mini/_settings
{
  "index": { "number_of_replicas": 1 }
}
text
GET _cat/indices/pratique-mini?v

Question 2.1. Quelle couleur observes-tu ?

text
PUT pratique-mini/_settings
{
  "index": { "number_of_replicas": 0 }
}
text
GET _cat/indices/pratique-mini?v

Question 2.2. Quelle couleur observes-tu ?

Question 2.3. Pourquoi la couleur passe-t-elle de jaune à vert quand le nombre de réplicas passe de 1 à 0 ? Que signifient ces deux états ?

Pour voir le rouge, un index dont la copie est exigée sur une machine qui n'existe pas :

text
PUT demo-red
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0,
    "index.routing.allocation.require._name": "noeud-inexistant"
  }
}
text
GET _cat/indices/demo-red?v

Question 2.4. Quelle couleur observes-tu, et pourquoi ?

On retire la contrainte, puis on relit :

text
PUT demo-red/_settings
{
  "index.routing.allocation.require._name": null
}
text
GET _cat/indices/demo-red?v

Question 2.5. Quelle couleur maintenant ?

Pour bien comprendre : lire les commandes de la partie 2
  • number_of_replicas dit combien de copies Elasticsearch doit placer en plus de l'original. 1 en demande une. 0 n'en demande aucune. Le labo n'a qu'une machine : une copie ne peut pas être placée sur une deuxième machine qui n'existe pas.
  • La couleur est la colonne health de GET _cat/indices/...?v. Relis cette colonne après chaque PUT _settings, pas le badge HTTP : un réglage accepté répond acknowledged: true même quand la couleur change.
  • PUT demo-red fixe trois réglages d'un coup. number_of_shards: 1 : un seul morceau. number_of_replicas: 0 : pas de copie. index.routing.allocation.require._name : « ce morceau ne peut aller que sur le nœud qui porte exactement ce nom ». noeud-inexistant n'est le nom d'aucune machine du labo.
  • Remettre ce réglage à null retire la contrainte. Le morceau peut alors se placer sur la machine qui tourne.

Partie 3 — Créer une fiche, la compléter, la chercher, la supprimer

On repart d'une armoire vide. La partie 3 reprend pratique-mini de zéro : les fiches de la partie 1 disparaissent ici.

text
DELETE pratique-mini
text
GET _cat/indices/pratique-*?v
text
PUT pratique-mini
text
GET _cat/indices/pratique-mini?v

Question 3.1. Pourquoi la couleur est-elle jaune ?

text
PUT pratique-mini/_settings
{
  "index": { "number_of_replicas": 0 }
}
text
GET _cat/indices/pratique-mini?v

Question 3.2. Pourquoi la couleur est-elle verte ?

text
PUT pratique-mini/_doc/1
{
  "titre": "Mon premier document"
}
text
GET pratique-mini/_doc/1
text
GET pratique-mini/_doc/3

À regarder : la fiche 1 répond "found": true. La fiche 3 répond "found": false : ce numéro n'existe pas.

text
POST pratique-mini/_update/1
{
  "doc": {
    "auteur": "Alice",
    "note": 5
  }
}

Question 3.3. À quoi sert cette commande ?

Question 3.4. Quelle commande affiche les informations générales de l'index (couleur, état, nombre de documents, taille) ? Quelle commande affiche les documents (titre, catégorie, niveau, langue) ?

Question 3.5. Peut-on faire un PUT à la place de ce POST _update ? Risque-t-on d'écraser la fiche ?

Question 3.6. La commande suivante écrase-t-elle la fiche existante, et pourquoi ?

text
PUT pratique-mini/_doc/1
{
  "titre": "Mon premier document"
}

Relis la fiche :

text
GET pratique-mini/_doc/1

On remet les champs effacés :

text
POST pratique-mini/_update/1
{
  "doc": {
    "auteur": "Alice",
    "note": 5
  }
}

Question 3.7. Ajoute une deuxième fiche (titre, auteur Bob, note 3), puis compte les fiches. Écris les commandes.

Question 3.8. Retrouve l'ensemble des fiches. Écris la commande.

Question 3.9. Retrouve la fiche dont le titre contient « premier ». Écris la commande.

Question 3.10. Supprime la fiche 2, puis l'index. Écris les commandes, puis vérifie avec GET _cat/indices/pratique-*?v.

Avant l'étape 1, supprime aussi les deux index de démonstration, sinon ils restent dans le labo :

text
DELETE pratique-mini-strict
text
DELETE demo-red
Pour bien comprendre : lire les commandes de la partie 3
  • DELETE pratique-mini enlève cette armoire et toutes ses fiches. pratique-mini-strict et demo-red ne sont pas touchés : un DELETE vise le nom que tu écris, pas « tout ce que tu as créé ».
  • GET _cat/indices/pratique-*?v. L'étoile veut dire « tout nom qui commence par pratique- ». Après le DELETE, pratique-mini ne doit plus être dans la liste. pratique-mini-strict y est encore.
  • PUT pratique-mini recrée une armoire vide. Sans corps, Elasticsearch choisit ses réglages par défaut, dont le nombre de copies. C'est ce défaut que la question 3.1 te fait observer.
  • GET pratique-mini/_doc/1 lit la fiche par son numéro, sans chercher. found vaut true quand le numéro existe. GET pratique-mini/_doc/3 vise un numéro que tu n'as pas créé : found vaut false, sans _source. Ce n'est pas une panne du labo.
  • POST pratique-mini/_update/1 ne remplace pas la fiche. Le mot doc dans le corps veut dire « fusionne ces champs avec ceux qui sont déjà là ». auteur et note s'ajoutent. titre n'est pas dans le corps, il reste.
  • GET _cat/indices/pratique-mini?v décrit l'armoire : couleur, état, nombre de fiches, taille. GET pratique-mini/_search décrit les fiches. Les deux ne répondent pas à la même question.
  • PUT pratique-mini/_doc/1 avec seulement titre envoie une fiche entière vers un numéro qui existe déjà. Compare avec _update : l'un envoie « la fiche complète », l'autre envoie « les champs à ajouter ».
  • Le second POST _update remet auteur et note après ce PUT. Sans lui, la fiche 1 n'aurait plus que titre au moment d'ajouter la fiche 2.
  • _count renvoie un nombre. _search sans corps renvoie les fiches. _search avec query / match ne garde que les fiches dont le champ contient le mot demandé.
  • DELETE pratique-mini/_doc/2 enlève une fiche. DELETE pratique-mini enlève l'armoire. DELETE pratique-mini-strict et DELETE demo-red enlèvent les deux index de démonstration, pour que l'étape 1 reparte d'un labo sans tes essais.

Réponses

Ouvre une solution après avoir répondu.

Partie 1

Solution : question 1

Question 1. Quelle est la différence entre PUT et POST ?

PUT range la fiche à l'adresse que tu as écrite. POST range une fiche et laisse Elasticsearch inventer l'adresse.

Imagine une armoire d'école. Chaque fiche a un numéro collé dessus, son _id. C'est ce numéro que tu tapes ensuite dans GET …/_doc/1.

PUT pratique-mini/_doc/1 dit : « range cette fiche dans le tiroir 1 ». Tu as choisi le 1. La fiche Docker porte donc "_id": "1". PUT pratique-mini/_doc/3 fait la même chose pour le tiroir 3. Personne n'a créé le 2 : les numéros ne se suivent pas tout seuls, c'est toi qui les donnes.

POST pratique-mini/_doc s'arrête à _doc. Il n'y a pas de numéro dans le chemin. Elasticsearch invente alors un _id long, du genre W8k3nYQBR…. C'est comme demander à la bibliothécaire : « range cette fiche où tu veux, et dis-moi le numéro après ».

Tape GET pratique-mini/_search et ouvre chaque _id :

  • "_id": "1" → le PUT de Docker ;
  • "_id": "3" → le PUT des LLMs ;
  • un _id illisible → le POST de Kubernetes.

Le même PUT une seconde fois sur _doc/1 remplace toute la fiche 1. Un second POST sans numéro ajoute une fiche de plus, avec un nouvel _id. C'est la différence à retenir : PUT = à cette adresse, POST = une fiche de plus.

Si tu corriges le titre de Docker, tu refais PUT pratique-mini/_doc/1 avec le nouveau JSON. La fiche 1 change, les autres ne bougent pas. Si tu ajoutes un quatrième cours avec POST pratique-mini/_doc, tu obtiens une quatrième fiche : tu ne touches pas aux trois premières.

Solution : question 2

Question 2. Peut-on ajouter un champ nouveau, par exemple langue, à un document ?

Oui. Par défaut, Elasticsearch accepte le champ et l'ajoute au plan de l'armoire, sans que tu recréés l'index.

Dans pratique-mini, tu n'as jamais déclaré de colonnes. Les trois premières fiches ont titre, categorie, niveau. Puis tu ranges la fiche 5 avec un champ de plus, langue: "fr". Elasticsearch ne dit pas « cette colonne n'existe pas ». Il dit « d'accord », et il ajoute langue au mapping.

C'est le mapping dynamique : le plan de l'armoire grandit tout seul à la première fiche qui apporte un champ nouveau. Tu n'as pas à faire DELETE puis PUT de l'index.

Les fiches 1 et 3 n'ont pas langue. Ce n'est pas une erreur. Une fiche n'est pas obligée d'avoir tous les champs des autres. Relis-les avec GET pratique-mini/_doc/1 : tu ne vois que les trois champs d'origine. Relis la 5 : tu vois les quatre.

Un catalogue de cours, même idée. Les premiers n'ont pas de prix. Un jour tu ranges un cours payant avec "prix": 49. Elasticsearch ajoute prix au mapping. Les anciens cours restent lisibles, simplement sans prix. C'est pratique pour commencer. C'est aussi le risque de la question 3 : n'importe quel champ mal nommé (prx, languee) entre de la même façon.

Solution : question 3

Question 3. Comment déclarer les champs autorisés et leur type, pour refuser une donnée hors plan ?

On crée l'index avec un mapping "dynamic": "strict" et une liste properties. Tout champ absent de cette liste est refusé.

pratique-mini acceptait tout. pratique-mini-strict est l'armoire inverse : le plan est écrit avant la première fiche.

text
"dynamic": "strict"

veut dire : si un champ n'est pas dans properties, refuse la fiche entière. Pas « ignore le champ », pas « ajoute-le quand même ». Refuse.

La liste déclare quatre champs et leur type :

  • titre en text : on pourra chercher des mots dedans (« Docker », « Kubernetes ») ;
  • categorie, niveau, langue en keyword : on comparera la valeur exacte (« DevOps », pas « devops quelque chose »).

La fiche 5 passe : titre, categorie, niveau, langue. Rien de plus. La fiche 6 ajoute prix: 100. prix n'est pas dans le plan. Elasticsearch répond une erreur du genre strict_dynamic_mapping_exception et nomme le champ prix. La fiche n'est pas rangée.

Un formulaire d'inscription n'accepte que nom, e-mail, âge. Quelqu'un ajoute une case « salaire ». Le formulaire refuse. Le mapping strict fait la même chose pour une fiche JSON. Sans lui, le salaire entrerait, et le jour où tu veux calculer une moyenne d'âge, tu te retrouves avec un champ salaire que personne n'avait prévu.

Solution : question 4

Question 4. Dans quels cas concrets utilise-t-on un mapping strict ?

Dès qu'une donnée fausse, mal nommée ou imprévue ne doit pas entrer dans l'index.

Le mapping dynamique est confortable pour un atelier. En production, un champ de trop coûte cher : une recherche qui ne trouve plus, un tableau de bord qui mélange des types, une donnée sensible rangée dans un champ inventé par une faute de frappe.

Cas où le strict est le bon réflexe :

  • Banque. Un virement a un montant, une date, un IBAN. Un champ montant_bis créé par une typo ne doit pas entrer.
  • Dossier médical. Le groupe sanguin, la date d'admission. Un champ notes_perso inventé par une appli tierce ne doit pas se ranger à côté.
  • Entrepôt. Chaque produit a un code, une quantité, un emplacement. Si l'équipe A écrit qte et l'équipe B quantite, tu ne pourras plus additionner les stocks.
  • Cybersécurité. Des journaux viennent de dix serveurs. S'ils n'ont pas les mêmes noms de champs, tu ne pourras plus filtrer « toutes les connexions échouées ».
  • API partagée. Trois équipes envoient des fiches dans le même index. Sans plan, chacune invente ses noms (client_id, id_client, clientId). Le strict force un seul nom.

Ce que le strict refuse, avec un exemple pour chacun :

  • "quantite": "beaucoup" dans un champ nombre. Tu ne pourras plus faire une moyenne.
  • "date_reception": "hier". Une date doit ressembler à 2026-09-21, pas à un mot.
  • "quantitee": 12 (deux e). Faute de frappe : le champ autorisé s'appelle quantite. Sans strict, tu aurais deux colonnes et la vraie resterait vide.
  • "age": 18.5 dans un champ entier. Un âge en demi-année n'est pas le type déclaré.
  • "actif": "oui" dans un booléen. Seuls true et false passent.
  • trois noms pour le même client. Le strict n'en autorise qu'un, celui du plan.
  • un produit sans emplacement alors que tous les autres en ont un, si tu as déclaré le champ comme obligatoire côté application — le mapping, lui, refuse surtout les champs en trop.
  • "numero_carte": "4111…" envoyé par erreur dans un index de catalogues. Le champ n'est pas prévu : la fiche est refusée, la donnée sensible n'est pas stockée.
  • des journaux Linux et Windows qui n'utilisent pas les mêmes clés. Le strict impose les clés du plan, les autres sources doivent s'adapter.
  • la création automatique de dizaines de champs inutiles (tmp, debug, test1) qui gonflent l'index pour rien.

Règle simple. Atelier, exploration, tu laisses le dynamique. Index partagé, argent, santé, stocks, journaux : tu écris le plan, tu mets strict.

Partie 2

Solution : question 2.1

Question 2.1. Quelle couleur observes-tu ?

Jaune.

Après number_of_replicas: 1, la colonne health de GET _cat/indices/pratique-mini?v dit yellow. Tes fiches sont toujours là. Tu peux encore faire GET _doc/1. Jaune ne veut pas dire « cassé ». Ça veut dire : « l'original est là, la copie demandée n'est pas là ».

Exemple. Tu photocopies un dossier pour le mettre dans un deuxième bureau. Le deuxième bureau n'existe pas. Le dossier original est sur ton bureau : tu travailles. L'alarme est jaune parce que la photocopie n'a nulle part où aller.

Solution : question 2.2

Question 2.2. Quelle couleur observes-tu ?

Vert.

Après number_of_replicas: 0, la même commande montre green et rep 0. Tu n'as plus demandé de copie. Rien ne manque. Vert veut dire : « tout ce qui a été demandé est en place ».

Exemple. Tu ranges le dossier dans un seul tiroir, et tu n'as pas demandé de photocopie. Personne n'attend une deuxième machine. L'alarme redevient verte.

Solution : question 2.3

Question 2.3. Pourquoi la couleur passe-t-elle de jaune à vert quand les réplicas passent de 1 à 0 ?

Parce que le labo n'a qu'une machine. Avec 1 réplica, Elasticsearch doit poser une copie sur une autre machine. Cette machine n'existe pas. La copie manque → jaune. Avec 0 réplica, aucune copie n'est demandée. Rien ne manque → vert.

Les trois couleurs, dites simplement :

  • Vert. L'original est là, et toutes les copies que tu as demandées sont là aussi. Tu peux lire et écrire. Si une machine tombe, une copie peut prendre le relais — à condition d'avoir demandé des copies et d'avoir plusieurs machines.
  • Jaune. L'original est là. Au moins une copie manque. Tu continues à travailler. Tu n'as plus de filet : si la machine de l'original tombe, ces fiches disparaissent.
  • Rouge. Une partie de l'original n'est pas là. Certaines fiches sont illisibles. C'est la seule couleur où tu perds des lectures.

Exemple de tous les jours. Un devoir :

  • vert : tu as ta copie, et tu as donné une photocopie à un camarade ;
  • jaune : tu as ta copie, tu avais promis une photocopie, tu n'as personne à qui la donner ;
  • rouge : tu as perdu ta copie. Personne ne peut plus la lire.

Dans le labo, on reste volontairement à 0 réplica. Une seule machine ne peut pas héberger à la fois l'original et sa copie : Elasticsearch refuse de poser les deux au même endroit. C'est pour ça que les index du kit (cours, avis, acces) sont verts : leur mapping fixe déjà number_of_replicas: 0.

Solution : question 2.4

Question 2.4. Quelle couleur observes-tu, et pourquoi ?

Rouge. Parce que l'original lui-même n'a nulle part où se poser.

demo-red dit : « ce morceau d'index ne peut aller que sur le nœud noeud-inexistant ». Aucune machine du labo ne s'appelle comme ça. Elasticsearch ne pose donc pas le shard principal. Sans original, la couleur est rouge. GET _cat/indices/demo-red?v le montre.

C'est différent du jaune. En jaune, tes fiches Docker et Kubernetes se lisaient encore. Ici, même l'armoire n'est pas placée. Ranger une fiche dans demo-red maintenant échouerait : il n'y a pas de tiroir physique.

Exemple. Tu expédies un colis à « 12, rue qui n'existe pas ». Le colis n'arrive nulle part. Ce n'est pas « en attente de photocopie ». C'est « jamais livré ».

Solution : question 2.5

Question 2.5. Quelle couleur maintenant ?

Vert.

null retire la contrainte de nom. Elasticsearch n'exige plus le nœud fantôme. Il pose le shard sur la machine du labo, celle qui tourne. L'original est en place, aucun réplica n'est demandé (number_of_replicas: 0) : tout ce qui est demandé est là → vert.

Exemple. Tu enlèves l'étiquette « livrer uniquement au bureau inexistant ». Le colis va au bureau réel. Il est arrivé.

Partie 3

Solution : question 3.1

Question 3.1. Pourquoi la couleur est-elle jaune ?

Parce qu'un PUT pratique-mini sans corps reprend les réglages par défaut, et le défaut demande 1 réplica.

Tu viens d'effacer l'index et de le recréer vide. Tu n'as envoyé aucun settings. Elasticsearch choisit alors : 1 shard, 1 réplica. Une seule machine ne peut pas héberger cette copie. Même situation qu'à la question 2.1, pour la même raison.

docs.count vaut 0 : l'armoire est vide. Jaune n'a rien à voir avec le nombre de fiches. Une armoire vide peut être jaune. Une armoire pleine aussi. La couleur parle des copies, pas du contenu.

Exemple. Tu achètes une armoire neuve. La notice dit « prévoir une copie de secours ». Tu n'as qu'une pièce. L'alarme est jaune dès la sortie du carton, avant d'y ranger la moindre feuille.

Solution : question 3.2

Question 3.2. Pourquoi la couleur est-elle verte ?

Parce que tu as dit number_of_replicas: 0. Plus de copie exigée, plus de manque, vert.

C'est le même geste que dans la partie 2, et le même que les index du kit. Sur une machine, c'est le réglage juste.

Exemple. Tu barres sur la notice la ligne « copie de secours ». L'alarme s'éteint. L'armoire est toujours vide, mais elle est verte.

Solution : question 3.3

Question 3.3. À quoi sert POST pratique-mini/_update/1 ?

À compléter la fiche 1 sans jeter ce qui est déjà écrit.

Le mot doc dans le corps veut dire « fusionne ces champs avec la fiche actuelle ». Tu envoies auteur et note. titre n'est pas dans le corps : il reste. Après un GET _doc/1, tu dois voir les trois.

Ce n'est pas un PUT. Un PUT dirait « voici la fiche entière, jette l'ancienne ». _update dit « ajoute ou change seulement ce que je t'envoie ».

Exemple. Une fiche élève a déjà « nom : Alice ». Tu ajoutes « note : 5 » avec _update. Le nom est toujours là. Si tu avais fait un PUT avec seulement { "note": 5 }, le nom disparaissait. C'est exactement le piège des questions 3.5 et 3.6.

Solution : question 3.4

Question 3.4. Quelle commande décrit l'armoire ? Quelle commande décrit les fiches ?

L'armoire :

text
GET _cat/indices/pratique-mini?v

Une ligne. Tu y lis la couleur (health), si l'index est ouvert (status), le nombre de fiches (docs.count), la taille sur disque. Tu n'y lis aucun titre, aucun auteur. C'est la plaque sur la porte de l'armoire, pas les feuilles à l'intérieur.

Les fiches :

text
GET pratique-mini/_search

Le JSON des documents. Chaque hit a un _id et un _source : titre, et plus tard auteur, note. C'est ouvrir l'armoire et étaler les feuilles sur la table.

Exemple. Tu veux savoir « combien de dossiers, et est-ce vert ? » → _cat/indices. Tu veux savoir « qu'est-ce qu'il y a écrit sur la fiche d'Alice ? » → _search, ou GET …/_doc/1 si tu as déjà le numéro.

Solution : question 3.5

Question 3.5. Peut-on faire un PUT à la place de _update ? Y a-t-il un risque d'écraser ?

Oui, le PUT est accepté. Oui, il y a un risque : il remplace toute la fiche.

Elasticsearch ne refuse pas PUT pratique-mini/_doc/1. Le numéro 1 existe, le verbe est bon, le JSON est bon. La requête répond "result": "updated". Ça a l'air réussi.

Le piège est dans le corps. _update envoie seulement les champs à ajouter. PUT _doc/1 envoie la fiche complète. Tout ce qui n'est pas dans ce JSON disparaît.

Si tu copies le PUT de l'étape « premier document », le corps n'a que titre. auteur et note sont effacés, même si la requête « marche ».

Exemple. Tu corriges une fiche papier. _update, c'est ajouter une ligne au stylo. PUT, c'est jeter la fiche et en réécrire une nouvelle avec seulement ce que tu as sous les yeux. Si tu as oublié deux lignes, elles n'existent plus.

Solution : question 3.6

Question 3.6. Cette commande écrase-t-elle la fiche, et pourquoi ?

Oui. Parce que PUT _doc/1 ne fusionne pas : il remplace le document entier par le JSON envoyé.

Après le GET pratique-mini/_doc/1, _source ne contient plus que "titre": "Mon premier document". auteur et note ont disparu. "_version" a augmenté : Elasticsearch a bien écrit. Il a écrit moins que ce qu'il y avait.

Le POST _update qui suit n'est pas décoratif. Il remet auteur et note. Sans lui, la fiche 1 resterait incomplète pour la suite (deuxième fiche, recherche sur « premier »).

Règle à retenir, la même qu'à l'étape 6 : PUT remplace, _update complète.

Exemple. Même fiche Alice. Tu fais PUT avec seulement le titre. C'est comme photocopier une page blanche où tu n'as réécrit que le titre, puis jeter l'original. Relire la fiche le prouve : plus de note, plus d'auteur.

Solution : question 3.7

Question 3.7. Ajoute une deuxième fiche, puis compte.

Tu ranges une fiche nouvelle, donc un _id que tu choisis, ici 2. Un PUT est juste : le tiroir 2 est vide, tu ne risques pas d'écraser Alice.

text
PUT pratique-mini/_doc/2
{
  "titre": "Deuxième document, écrit par Bob",
  "auteur": "Bob",
  "note": 3
}

Tu dois voir "result": "created" et "_id": "2". Puis :

text
GET pratique-mini/_count

count vaut 2 : Alice et Bob. _count ne montre pas les titres. Il répond seulement « combien ». Si tu viens d'écrire et que tu lis 1, attends une seconde et relance : la recherche (et donc _count) voit les nouvelles fiches avec un tout petit délai. GET _doc/2, lui, est immédiat.

Exemple. Deux dossiers dans l'armoire. Tu ne les ouvres pas. Tu dis juste « il y en a deux ». C'est _count.

Solution : question 3.8

Question 3.8. Retrouve l'ensemble des fiches.

text
GET pratique-mini/_search

Sans corps, sans query. Elasticsearch comprend : « tout ». Tu obtiens hits.total.value: 2 et deux _source : Alice (fiche 1) et Bob (fiche 2). L'ordre des deux peut changer : sans critère, les deux ont le même score.

C'est la commande de la question 3.4, côté fiches. _cat te dirait encore docs.count 2, sans montrer Alice ni Bob.

Exemple. Tu ouvres l'armoire et tu sors toutes les feuilles, sans tri. Tu les as toutes, tu ne cherches pas un mot.

Solution : question 3.9

Question 3.9. Retrouve la fiche dont le titre contient « premier ».

text
GET pratique-mini/_search
{
  "query": {
    "match": {
      "titre": "premier"
    }
  }
}

match cherche un mot dans le champ titre. La fiche 1 a « Mon premier document » : le mot premier est dedans. La fiche 2 a « Deuxième document, écrit par Bob » : pas ce mot. Une seule hit, "_id": "1".

Ce n'est pas un GET _doc/1. Tu n'as pas besoin de connaître le numéro. Tu poses une question sur le texte. GET _doc/1 va droit au tiroir. _search + match parcourt les feuilles.

Exemple. Dans une bibliothèque : « donne-moi le livre numéro 1 » (_doc/1) contre « donne-moi les livres dont le titre contient premier » (match). Le second marche même si tu as oublié le numéro.

Premier avec une majuscule marcherait aussi : match sur un champ text ne tient pas compte de la casse. C'est pour plus tard, le module sur les analyseurs.

Solution : question 3.10

Question 3.10. Supprime la fiche 2, puis l'index.

D'abord la feuille, ensuite l'armoire. L'ordre compte pour comprendre les deux DELETE.

text
DELETE pratique-mini/_doc/2

"result": "deleted". Bob n'est plus là. Alice est encore dans le tiroir 1. _count passe à 1. L'armoire existe toujours.

text
DELETE pratique-mini

L'armoire entière disparaît, Alice comprise. GET pratique-mini/_doc/1 ne répond plus "found": false : il répond index_not_found_exception. Plus de tiroir, plus de fiche.

text
GET _cat/indices/pratique-*?v

La ligne pratique-mini n'y est plus. S'il reste pratique-mini-strict ou demo-red, les deux DELETE donnés juste avant l'étape 1 les enlèvent.

Exemple. Tu jettes la copie de Bob (_doc/2). Le classeur est encore dans l'étagère. Puis tu jettes le classeur (DELETE pratique-mini). Demander la copie d'Alice n'a plus de sens : le classeur n'est plus là. Ce n'est pas « fiche introuvable », c'est « armoire introuvable ».

Les index du kit (cours, avis, acces) ne commencent pas par pratique-. Ils ne sont pas touchés. Tu peux enchaîner avec l'étape 1 : un PUT pratique-mini neuf.

Révisons les étapes en gros

Les trois parties ci-dessus, c'était le premier passage : tu as tapé, tu as répondu. Maintenant on refait le même parcours, plus lentement. Voici les huit étapes, en gros. Ensuite tu les ouvres une par une.

  1. Créer l'armoire. PUT pratique-mini. Rien dedans. Pas de colonnes, pas de fiche.
  2. La voir, et corriger sa couleur. GET _cat/indices/pratique-mini?v : jaune, 1 réplica. Puis number_of_replicas: 0 : vert.
  3. Ranger une première fiche. PUT pratique-mini/_doc/1 avec un titre. Tu choisis le numéro 1.
  4. Relire la fiche. GET pratique-mini/_doc/1 : "found": true et _source. Un numéro qui n'existe pas : "found": false.
  5. Ajouter des valeurs. POST pratique-mini/_update/1 : auteur et note s'ajoutent, titre reste. C'est le livrable.
  6. Le piège. Le même PUT _doc/1 qu'à l'étape 3. auteur et note disparaissent. PUT remplace, _update complète.
  7. Une deuxième fiche, compter, chercher. Fiche 2 (Bob), _count = 2, _search liste les deux, match sur « premier » ne garde que la 1.
  8. Supprimer. DELETE la fiche 2, puis DELETE l'armoire. pratique-* est vide.

Ouvre chaque étape. Tape. Compare avec le JSON. C'est le même pratique-mini, repris depuis zéro.

Étape 1 — Créer l'armoire, vide

Afficher l'étape
text
PUT pratique-mini

Ce que la requête demande : crée un index qui s'appelle pratique-mini. Rien d'autre : pas de colonnes, pas de contenu.

json
{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "pratique-mini"
}

À regarder : "acknowledged": true, « c'est fait », et le nom en écho. Le badge en haut à droite de la réponse dit 200 - OK.

Pour bien comprendre
  • Pourquoi pratique- devant ? Tous les index que tu crées dans ce cours portent ce préfixe. Ainsi GET _cat/indices/pratique-*?v liste tout ce qui est à toi et rien d'autre, et cours, avis, acces restent intouchés.
  • Un nom d'index est en minuscules, sans espace ni majuscule ni /. Pratique-Mini serait refusé.
  • Une seconde fois la même requête répond 400 avec resource_already_exists_exception : l'armoire existe déjà. Ce n'est pas une panne, c'est une réponse.

Étape 2 — La voir, et corriger sa couleur

Afficher l'étape
text
GET _cat/indices/pratique-mini?v

Ce que la requête demande : une ligne de résumé sur cet index, avec la ligne d'en-tête (?v, verbose).

text
health status index         uuid                   pri rep docs.count docs.deleted store.size pri.store.size dataset.size
yellow open   pratique-mini YHjAfGXBTwSZcl7CLcc2jw   1   1          0            0       227b           227b         227b

À regarder : docs.count 0, l'armoire est vide. Et health yellow avec rep 1 : Elasticsearch a prévu une copie de secours (un réplica) de ton index sur une deuxième machine, et le labo n'en a qu'une. La copie ne peut être placée nulle part, d'où le jaune. Les trois index du kit sont verts parce que leur mapping fixe number_of_replicas: 0. Fais pareil, en une requête :

text
PUT pratique-mini/_settings
{
  "index": { "number_of_replicas": 0 }
}
json
{
  "acknowledged": true
}

Retape GET _cat/indices/pratique-mini?v :

text
health status index         uuid                   pri rep docs.count docs.deleted store.size pri.store.size dataset.size
green  open   pratique-mini YHjAfGXBTwSZcl7CLcc2jw   1   0          0            0       227b           227b         227b

À regarder : green, rep 0. Ton uuid sera différent : c'est l'identifiant interne de l'index, tiré au hasard à la création.

Pour bien comprendre
  • Jaune n'est pas cassé. Un index jaune se lit et s'écrit normalement. C'est un avertissement : « la copie de secours que tu as demandée n'existe pas ». Sur une seule machine, elle ne peut pas exister.
  • Pendant que ton index était jaune, GET _cluster/health disait "status": "yellow" pour tout le cluster : la couleur du cluster est la pire couleur de ses index. C'est l'explication de la panne « yellow » du catalogue de la leçon 04.
  • GET pratique-mini (sans _cat) rend la fiche complète de l'index : "mappings": { } (vide, aucune fiche rangée) et "settings" avec number_of_replicas.

Étape 3 — Ranger une première fiche

Afficher l'étape
text
PUT pratique-mini/_doc/1
{
  "titre": "Mon premier document"
}

Ce que la requête demande : dans l'armoire pratique-mini, range une fiche (_doc) numéro 1 qui contient un champ titre.

json
{
  "_index": "pratique-mini",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

À regarder : "result": "created" et "_version": 1 : première version de la fiche 1. Équivalent SQL : INSERT INTO pratique_mini (id, titre) VALUES (1, 'Mon premier document'), sauf qu'aucun CREATE TABLE n'a été nécessaire.

Pour bien comprendre
  • Le mapping vient de naître. Tape GET pratique-mini/_mapping : le champ titre est maintenant déclaré de type text (pour chercher des mots dedans) avec un sous-champ titre.keyword (pour trier ou filtrer sur la valeur exacte). Elasticsearch l'a déduit de la valeur "Mon premier document", une chaîne.
  • Le 1 de _doc/1, c'est toi qui l'as choisi. Les documents du kit font pareil (C0001, A00001…). Si tu écris POST pratique-mini/_doc sans numéro, Elasticsearch invente un _id de vingt caractères ; pratique pour des journaux, pénible pour une fiche que tu veux retrouver à la main.
  • _shards, _seq_no, _primary_term sont de la comptabilité interne (sur combien de morceaux l'écriture a été confirmée, quel numéro d'ordre). Tu n'en as pas besoin dans ce cours.

Étape 4 — Relire la fiche

Afficher l'étape
text
GET pratique-mini/_doc/1

Ce que la requête demande : donne-moi la fiche numéro 1 de pratique-mini, directement, sans chercher.

json
{
  "_index": "pratique-mini",
  "_id": "1",
  "_version": 1,
  "_seq_no": 0,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "titre": "Mon premier document"
  }
}

À regarder : "found": true, et _source, ta fiche telle que tu l'as écrite, au caractère près. Équivalent SQL : SELECT * FROM pratique_mini WHERE id = 1.

Essaie une fiche qui n'existe pas : GET pratique-mini/_doc/3.

json
{
  "_index": "pratique-mini",
  "_id": "3",
  "found": false
}

Pas d'erreur, pas de _source : "found": false, badge 404 - Not Found. Elasticsearch a compris la question ; la réponse est « il n'y a rien à ce numéro ».

Étape 5 — Ajouter des valeurs à la fiche

Afficher l'étape
text
POST pratique-mini/_update/1
{
  "doc": {
    "auteur": "Alice",
    "note": 5
  }
}

Ce que la requête demande : mets à jour (_update) la fiche 1 en y ajoutant ces deux champs. Ce qui n'est pas mentionné (titre) reste tel quel.

json
{
  "_index": "pratique-mini",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

À regarder : "result": "updated", "_version": 2. Relis la fiche avec GET pratique-mini/_doc/1 :

json
{
  "_index": "pratique-mini",
  "_id": "1",
  "_version": 2,
  "_seq_no": 1,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "titre": "Mon premier document",
    "note": 5,
    "auteur": "Alice"
  }
}

Trois champs. Le titre est toujours là. Équivalent SQL : UPDATE pratique_mini SET auteur = 'Alice', note = 5 WHERE id = 1, à la différence près qu'en SQL les colonnes auteur et note auraient dû exister avant. C'est ta réponse-livrable : garde-la.

Pour bien comprendre
  • Le mot doc dans le corps veut dire « voici les champs à fusionner ». Sans lui, _update ne sait pas quoi faire.
  • Le mapping a grandi. GET pratique-mini/_mapping montre maintenant auteur (text + keyword, comme titre) et note de type long, un entier. Elasticsearch a deviné le type à partir de 5. Si tu avais écrit "note": "5" entre guillemets, il aurait déclaré du texte, et tu n'aurais plus pu calculer une moyenne dessus. C'est le sujet de la leçon sur le mapping, au module 2.
  • _version compte les écritures sur cette fiche, pas les lectures : GET ne l'incrémente jamais.

Étape 6 — Le piège : PUT remplace tout

Afficher l'étape

Renvoie exactement la requête de l'étape 3 :

text
PUT pratique-mini/_doc/1
{
  "titre": "Mon premier document"
}
json
{
  "_index": "pratique-mini",
  "_id": "1",
  "_version": 3,
  "result": "updated",
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 3,
  "_primary_term": 1
}

À regarder : "result": "updated" (pas created : la fiche 1 existait) et "_version": 3. Puis relis-la :

json
{
  "_index": "pratique-mini",
  "_id": "1",
  "_version": 3,
  "_seq_no": 3,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "titre": "Mon premier document"
  }
}

auteur et note ont disparu. PUT _doc/1 ne modifie pas la fiche 1 : il la remplace par ce que tu envoies. Pour compléter sans perdre, c'est POST _update/1 avec doc. Retiens la règle avec les deux verbes : PUT remplace, _update complète. Remets les deux champs avec la requête de l'étape 5 avant de continuer (tu obtiens _version: 4).

Étape 7 — Une deuxième fiche, compter, chercher

Afficher l'étape
text
PUT pratique-mini/_doc/2
{
  "titre": "Deuxième document, écrit par Bob",
  "auteur": "Bob",
  "note": 3
}

Réponse : "_id": "2", "result": "created", "_version": 1. Puis compte :

text
GET pratique-mini/_count
json
{
  "count": 2,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  }
}

Équivalent SQL : SELECT COUNT(*) FROM pratique_mini. Maintenant, vois tout ce qu'il y a dedans :

text
GET pratique-mini/_search

Ce que la requête demande : cherche dans pratique-mini, sans critère, donc tout.

json
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "pratique-mini",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "titre": "Deuxième document, écrit par Bob",
          "auteur": "Bob",
          "note": 3
        }
      },
      {
        "_index": "pratique-mini",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "titre": "Mon premier document",
          "note": 5,
          "auteur": "Alice"
        }
      }
    ]
  }
}

À regarder : hits.total.value: 2 (combien de fiches répondent) puis hits.hits, la liste des fiches, chacune avec son _id et son _source. L'ordre des deux peut varier : sans critère, toutes ont le même _score de 1.0. Équivalent SQL : SELECT * FROM pratique_mini.

Enfin, cherche un mot :

text
GET pratique-mini/_search
{
  "query": {
    "match": {
      "titre": "premier"
    }
  }
}

Ce que la requête demande : les fiches dont le champ titre contient le mot premier.

json
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.3788134,
    "hits": [
      {
        "_index": "pratique-mini",
        "_id": "1",
        "_score": 0.3788134,
        "_source": {
          "titre": "Mon premier document",
          "note": 5,
          "auteur": "Alice"
        }
      }
    ]
  }
}

À regarder : une seule fiche, la 1, et un _score qui n'est plus 1.0 : c'est la pertinence, « à quel point cette fiche répond à la question ». Le module 3 est consacré à ce chiffre. Équivalent SQL approximatif : SELECT * FROM pratique_mini WHERE titre LIKE '%premier%', sauf que match trouverait aussi Premier avec une majuscule, et le module 2 t'expliquera pourquoi.

Pour bien comprendre
  • _count rend 0 ou 1 juste après une écriture ? Elasticsearch rend les nouvelles fiches visibles à la recherche toutes les secondes, pas à l'instant même. Relance _count : il est à jour. GET _doc/1, lui, est toujours immédiat parce qu'il ne cherche pas, il va droit au numéro. Si tu veux forcer la visibilité immédiate dans un test : PUT pratique-mini/_doc/2?refresh=true.
  • took est le temps de la recherche en millisecondes. timed_out: false : elle a fini dans les délais.
  • Pourquoi GET avec un corps ? C'est une particularité d'Elasticsearch : la recherche est une lecture, donc GET, mais la question tient dans un corps JSON. POST pratique-mini/_search avec le même corps marche aussi ; les deux sont acceptés.

Étape 8 — Supprimer une fiche, puis l'armoire

Afficher l'étape
text
DELETE pratique-mini/_doc/2
json
{
  "_index": "pratique-mini",
  "_id": "2",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 4,
  "_primary_term": 1
}

À regarder : "result": "deleted". GET pratique-mini/_count rend 1 (au bout d'une seconde). Équivalent SQL : DELETE FROM pratique_mini WHERE id = 2.

Puis supprime l'armoire entière, fiches comprises :

text
DELETE pratique-mini
json
{
  "acknowledged": true
}

Preuve qu'elle n'existe plus, GET pratique-mini/_doc/1 :

json
{
  "error": {
    "root_cause": [
      {
        "type": "index_not_found_exception",
        "reason": "no such index [pratique-mini]",
        "resource.type": "index_or_alias",
        "resource.id": "pratique-mini",
        "index_uuid": "_na_",
        "index": "pratique-mini"
      }
    ],
    "type": "index_not_found_exception",
    "reason": "no such index [pratique-mini]",
    "resource.type": "index_or_alias",
    "resource.id": "pratique-mini",
    "index_uuid": "_na_",
    "index": "pratique-mini"
  },
  "status": 404
}

À regarder : la différence avec l'étape 4. Fiche absente dans une armoire présente : "found": false, sans erreur. Armoire absente : index_not_found_exception, 404. Les deux sont des réponses normales d'un service qui tourne. Équivalent SQL : DROP TABLE pratique_mini.

Vérification finale

text
GET _cat/indices/pratique-*?v

Réponse attendue : la ligne d'en-tête seule. Rien à toi ne traîne dans le cluster, et GET _cat/indices/cours,avis,acces?v montre toujours 504, 609, 12000.

  • Tu as créé pratique-mini et tu sais pourquoi il était jaune, puis vert.
  • Tu as rangé la fiche 1 avec PUT _doc/1 et relue avec GET _doc/1.
  • Tu as ajouté auteur et note avec POST _update/1 sans perdre titre.
  • Tu as vu PUT _doc/1 effacer les deux champs, et tu sais dire la règle : PUT remplace, _update complète.
  • _count a dit 2, _search a listé les deux fiches, match n'en a gardé qu'une.
  • Tu as supprimé la fiche 2 puis l'index, et pratique-* est vide.
  • Tu as gardé la réponse de GET pratique-mini/_doc/1 à trois champs (étape 5) comme livrable.

Si ça coince

Afficher les cas fréquents
  • 400 avec Unexpected character ou was expecting double-quote to start field name → le JSON du corps est mal formé : chaque nom de champ et chaque texte entre guillemets doubles ", une virgule entre les champs, pas de virgule après le dernier. Dev Tools souligne l'endroit.
  • 400 avec resource_already_exists_exception sur PUT pratique-mini → l'index existe déjà (tu as relancé l'étape 1). Continue à l'étape 2, ou DELETE pratique-mini pour repartir de zéro.
  • 400 avec no handler found for uri → faute de frappe dans un mot en _ : _serch, _doc/ oublié, _udpate. Elasticsearch valide le chemin avant tout le reste.
  • 405 avec Incorrect HTTP method for uri [/pratique-mini/_update/1] and method [GET], allowed: [POST] → mauvais verbe pour ce chemin. Le message dit lui-même lequel est accepté.
  • 400 avec [UpdateRequest] unknown field [titre] → tu as envoyé les champs directement à _update, sans les envelopper dans "doc": { … }. Ajoute l'enveloppe.
  • _count ou _search ne voient pas la fiche que tu viens d'écrire → attends une seconde et relance (voir « Pour bien comprendre » de l'étape 7). GET _doc/1 la voit tout de suite.
  • "result": "noop" sur _update → les valeurs envoyées étaient déjà celles de la fiche ; rien à changer, _version n'a pas bougé. Ce n'est pas une erreur.
  • "status": "yellow" persiste dans GET _cluster/health après l'étape 2 → un autre index à toi a encore rep 1. GET _cat/indices?v&health=yellow le désigne ; applique-lui le même _settings, ou supprime-le.
  • Dev Tools affiche « Kibana server is not ready yet » → Kibana redémarre ou attend Elasticsearch ; .\labo.ps1 etat ou ./labo.sh etat, puis la leçon 04.