FlowKit

Connecter Elasticsearch à n8n : indexer, chercher et alimenter un RAG

Publié le 26 août 2026 · 9 min de lecture

Elasticsearch apparaît dans deux conversations qui n'ont presque rien en commun. Dans la première, c'est le moteur derrière un Kibana, l'endroit où atterrissent des documents que l'on veut chercher en texte intégral. Dans la seconde, c'est un candidat sérieux au poste de brique de recherche d'un pipeline RAG, avec BM25 d'un côté et des vecteurs denses de l'autre. Le node Elasticsearch de n8n (n8n-nodes-base.elasticsearch) sert les deux, mais pas au même niveau : il couvre l'indexation et la recherche courante, et laisse le reste au node HTTP Request. Ce guide trace la frontière, avec les paramètres réels du node, les corps de requête à écrire à la main et les pièges.

Deux usages à ne pas confondre

Usage 1 — moteur de recherche et observabilité. n8n alimente un index (tickets, commandes, événements métier) ou l'interroge pour déclencher quelque chose. Le node natif suffit dans la grande majorité des cas.

Usage 2 — retriever d'un pipeline RAG. Le corpus est découpé en chunks, indexé, puis interrogé en BM25, en kNN vectoriel, ou les deux. Le node natif ne suffit plus : la recherche vectorielle passe obligatoirement par HTTP Request, et il faut comparer honnêtement le résultat à ce qu'offre une base vectorielle dédiée comme Qdrant.

Confondre les deux mène toujours à la même déception : un index créé à la va-vite pour du logging, puis recyclé en base de connaissances, mapping inadapté et aucun champ vectoriel.

La credential : trois champs, et c'est tout

La credential Elasticsearch de n8n est volontairement minimale :

  • Base URL — l'URL de votre cluster, port compris (https://es.mondomaine.fr:9200) ;
  • Username et Password — l'authentification basique ;
  • Ignore SSL Issues — une bascule pour tolérer un certificat auto-signé.

L'authentification basique est la seule méthode supportée : ni API key, ni Cloud ID. Sur Elastic Cloud, cela fonctionne quand même — l'endpoint du déploiement comme Base URL, un compte du cluster — mais si votre organisation impose des API keys, basculez sur un node HTTP Request avec une credential Header Auth portant Authorization: ApiKey <valeur encodée>. Le node HTTP Request sait aussi réutiliser la credential Elasticsearch via l'option Predefined Credential Type. Dans tous les cas, appliquez les principes du stockage sécurisé des credentials : un compte dédié à n8n, aux rôles limités aux index concernés, jamais le superutilisateur elastic.

Les opérations réelles du node

Ressource Index

Quatre opérations : Create, Delete, Get, Get Many. Le Create est plus riche qu'il n'en a l'air : ses Additional Fields incluent Aliases, Mappings, Settings et Wait for Active Shards. Vous pouvez donc créer un index correctement typé directement depuis n8n — c'est le geste décrit plus bas. Le Get Many, lui, se limite à Return All / Limit.

Ressource Document

Cinq opérations : Create, Delete, Get, Get Many, Update.

  • Create et Update utilisent le sélecteur habituel Data to Send / Fields to Send / Inputs to Ignore pour construire le document à partir des champs de l'item. Leurs options comprennent Refresh et, pour Create, Pipeline ID si un ingest pipeline doit enrichir le document.
  • Get accepte Source Includes, Source Excludes et Stored Fields, plus une bascule Simplify qui aplatit la réponse (_id et contenu de _source) au lieu de l'enveloppe brute d'Elasticsearch.
  • Get Many est de loin la plus fournie : au-delà de Return All et Limit, ses options couvrent Query, Query Parameters, Sort, Routing, Search Type, Track Scores, Track Total Hits, Explain, Terminate After, Timeout et Request Cache.

L'option Query est celle que la plupart des tutoriels ratent : elle accepte directement du Query DSL, avec un mécanisme de paramètres — vous écrivez $1, $2 dans la requête et fournissez les valeurs dans Query Parameters, exactement comme les requêtes préparées d'un node Postgres. L'option Sort, elle, attend des paires champ:direction séparées par des virgules, par exemple cree_le:desc,priorite:asc.

L'indexation en masse existe aussi, discrètement : Create, Update et Delete portent chacune une option booléenne (Bulk Create, Bulk Update, Bulk Delete) qui regroupe les items entrants et les envoie à l'API _bulk par paquets.

Ce qui reste du ressort du node HTTP Request

La liste des manques est courte mais structurante : _msearch, la recherche vectorielle knn, les agrégations (aggs), la pagination profonde search_after + PIT, le contrôle de concurrence optimiste (if_seq_no / if_primary_term), la mise à jour d'un mapping existant.

Pour un _bulk écrit à la main, le format est du NDJSON : une ligne d'action, une ligne de document, un retour à la ligne final obligatoire.

POST /tickets/_bulk
{"index":{"_id":"TCK-1042"}}
{"sujet":"Facture en double","statut":"ouvert","cree_le":"2026-08-26T09:12:00Z"}
{"index":{"_id":"TCK-1043"}}
{"sujet":"Mot de passe oublié","statut":"resolu","cree_le":"2026-08-26T09:14:00Z"}

Côté n8n : un corps Raw avec le content-type application/x-ndjson, construit par un node Code. Et surtout, lisez la réponse — un _bulk renvoie 200 OK même si la moitié des documents ont échoué. C'est le champ errors du corps qui compte, pas le code HTTP.

Une vraie requête _search, elle, ressemble à ceci :

{
  "query": {
    "bool": {
      "must": [{ "match": { "sujet": "facture" } }],
      "filter": [
        { "term": { "statut": "ouvert" } },
        { "range": { "cree_le": { "gte": "now-7d" } } }
      ]
    }
  },
  "size": 20,
  "sort": [{ "cree_le": "desc" }]
}

La distinction must / filter est décisive : filter ne participe pas au score et passe par le cache de filtres, alors que must fait entrer le terme dans le calcul de pertinence — le même raisonnement que le filtrage par métadonnées dans un RAG.

Poser le mapping avant d'indexer

Sans mapping explicite, Elasticsearch devine le type de chaque champ à la première insertion. Ce dynamic mapping se trompe de façon prévisible : une date écrite 26/08/2026 devient un text, un identifiant comme TCK-1042 est découpé en tokens et ne sera plus jamais retrouvé par une recherche exacte, un montant transmis en chaîne interdit tout range. Et un type de champ ne se modifie pas après coup : la seule sortie est un réindexage complet. D'où le geste — créer l'index avec ses mappings dès le départ, via Index → Create et son champ Mappings.

{
  "properties": {
    "sujet":     { "type": "text", "analyzer": "french" },
    "statut":    { "type": "keyword" },
    "client_id": { "type": "keyword" },
    "cree_le":   { "type": "date" },
    "embedding": { "type": "dense_vector", "dims": 1536, "index": true, "similarity": "cosine" }
  }
}

La règle mnémotechnique tient en une phrase : text pour ce qu'on cherche en langage naturel, keyword pour ce qu'on filtre, agrège ou trie.

Elasticsearch comme brique RAG

BM25, la fonction de pertinence d'Elasticsearch, n'est pas une astuce d'ingénierie : c'est l'aboutissement du Probabilistic Relevance Framework, dont Stephen Robertson et Hugo Zaragoza ont donné la synthèse de référence dans « The Probabilistic Relevance Framework: BM25 and Beyond », publié en 2009 dans Foundations and Trends in Information Retrieval (voir sur Google Scholar). Trente ans de littérature derrière un algorithme qui ne coûte rien à l'inférence : ne supposez jamais qu'un embedding fera forcément mieux.

Le benchmark BEIR de Nandan Thakur, Nils Reimers, Andreas Rücklé, Abhishek Srivastava et Iryna Gurevych — « BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models », NeurIPS Datasets and Benchmarks 2021 (voir sur Google Scholar) — l'a mesuré sur 18 jeux de données et 10 systèmes : BM25 reste une baseline remarquablement robuste hors domaine, quand plusieurs modèles denses excellents sur leur corpus d'entraînement se dégradent dès qu'on les déplace. Ne remplacez donc pas une recherche lexicale qui marche par des embeddings sans mesurer, et rappelez-vous que le choix du modèle d'embeddings pèse autant que celui du moteur.

Elasticsearch sait faire les deux : un champ dense_vector indexé — sur une structure HNSW, la même famille d'index que celle de pgvector — interrogé via la clause knn :

{
  "knn": {
    "field": "embedding",
    "query_vector": [0.021, -0.117, 0.083],
    "k": 10,
    "num_candidates": 100,
    "filter": { "term": { "client_id": "ACME" } }
  }
}

Le vecteur réel compte autant de dimensions que déclaré au mapping, et ce corps passe par HTTP Request : le node ne l'expose pas. Elasticsearch propose aussi un retriever rrf pour fusionner un query lexical et un knn, dont la disponibilité dépend de la licence du cluster. Le principe de cette fusion est détaillé dans notre guide de la recherche hybride pour RAG, et le gain se consolide presque toujours avec une étape de reranking.

Quatre cas d'usage concrets

  • Recherche interne sur les tickets support. Chaque ticket clos part dans un index, sujet en text et statut en keyword ; les agents retrouvent en une requête les cas similaires déjà traités — le complément naturel d'un scoring IA des tickets.
  • Logs métier applicatifs. Pas les logs système : Beats et Logstash restent bien meilleurs pour ça, et superviser une instance n8n relève d'autres outils. En revanche, les événements métier qui n'existent nulle part ailleurs (commande annulée, dossier requalifié) méritent leur index.
  • Alerte sur requête planifiée. Un Schedule Trigger toutes les quinze minutes, une opération Document → Get Many avec une Query filtrant sur cree_le >= now-15m, une notification si le compte dépasse un seuil.
  • Dashboard Kibana multi-sources. n8n agrège CRM, facturation et formulaires dans un index commun, Kibana affiche le tout — sans écrire un ETL.

Les pièges

  • Le plafond des 10 000 résultats. index.max_result_window limite from + size à 10 000 par défaut, et l'option Return All du node se traduit dans son code par un size fixé à 10 000. Au-delà, il faut search_after avec un point in time, donc HTTP Request et une boucle de pagination. Relever max_result_window est une fausse bonne idée : la mémoire consommée croît avec la profondeur.
  • Indexer document par document. Sans les options Bulk, chaque item déclenche une requête HTTP distincte. Sur 5 000 lignes, la différence se compte en minutes et en pression inutile sur le cluster.
  • Aucun contrôle de concurrence. Le node n'expose ni if_seq_no ni if_primary_term : deux workflows qui mettent à jour le même document s'écrasent en silence. Si l'ordre compte, sérialisez côté n8n ou passez par HTTP Request.
  • Le refresh n'est pas immédiat. Elasticsearch est near real-time, avec un rafraîchissement d'une seconde par défaut : un workflow qui indexe puis relit aussitôt trouvera un index vide. L'option Refresh (true ou wait_for) existe pour ces cas, à réserver aux petits volumes.
  • Un cluster sans authentification. Un Elasticsearch ouvert sur Internet sans mot de passe est un incident garanti, pas un risque. HTTPS, compte dédié, rôles restreints aux index concernés, Ignore SSL Issues réservé au laboratoire.

En résumé

Le node Elasticsearch couvre plus de terrain qu'on ne le croit : deux ressources, neuf opérations, une option Query qui accepte du Query DSL paramétré, des bascules Bulk. Ses limites sont nettes : pas de knn, pas d'agrégations, pas de search_after, pas de contrôle de concurrence, et une credential qui ne connaît que l'authentification basique. Le reste se joue au node HTTP Request. Et avant tout, posez le mapping : c'est la seule décision de ce guide qu'un réindexage complet sera nécessaire pour corriger.

Pour aller plus loin

Si votre objectif est un assistant qui répond sur vos documents, le Pack Assistant RAG (119 €) fournit la chaîne complète — découpage, embeddings, récupération et garde-fous anti-hallucination — à brancher sur Elasticsearch ou sur la base vectorielle de votre choix. Et si le corpus à indexer, ce sont vos emails et vos tickets entrants, le Pack Inbox IA (79 €) construit en amont la couche de tri qui décide ce qui mérite d'entrer dans l'index.

FAQ

Questions fréquentes

Le node Elasticsearch de n8n sait-il faire de l'indexation en masse ?

Oui, partiellement. Les opérations Create, Update et Delete de la ressource Document exposent une option booléenne (Bulk Create, Bulk Update, Bulk Delete) qui regroupe les items entrants et les envoie à l'API _bulk d'Elasticsearch par paquets, au lieu d'une requête HTTP par document. C'est très largement suffisant pour ingérer quelques milliers de lignes. En revanche vous ne choisissez ni la taille des paquets, ni le type d'action ligne par ligne, ni le pipeline appliqué à chaque document : pour cela, il faut construire le corps NDJSON vous-même et l'envoyer avec un node HTTP Request.

La credential Elasticsearch de n8n accepte-t-elle une API key ou un Cloud ID ?

Non. La credential Elasticsearch de n8n ne propose que trois champs — Base URL, Username, Password — plus une bascule Ignore SSL Issues. La seule méthode d'authentification supportée est l'authentification basique. Sur Elastic Cloud, cela fonctionne en renseignant l'endpoint du déploiement comme Base URL et un compte utilisateur du cluster ; le Cloud ID ne sert pas ici. Si votre politique de sécurité impose des API keys, passez par un node HTTP Request avec une credential Header Auth portant un en-tête Authorization de type ApiKey.

Pourquoi le node ne me renvoie-t-il jamais plus de 10 000 documents ?

Deux plafonds se cumulent. Côté n8n, l'option Return All de l'opération Get Many se traduit dans le code du node par un size fixé à 10 000. Côté Elasticsearch, le réglage index.max_result_window limite par défaut from + size à 10 000 documents, et une requête qui dépasse ce seuil renvoie une erreur explicite de fenêtre de résultats trop grande. Au-delà, il n'existe pas d'option magique : il faut paginer avec search_after associé à un point in time (PIT), donc passer par le node HTTP Request.

Faut-il choisir Elasticsearch ou une base vectorielle pour un RAG dans n8n ?

Cela dépend de ce que vous cherchez à retrouver. Si votre corpus est déjà dans Elasticsearch et que vos utilisateurs cherchent des références exactes — un numéro de facture, un code produit, une formulation précise — BM25 fait le travail sans embeddings et sans coût d'inférence. Si les requêtes sont formulées en langage naturel et que la reformulation est la norme, une base vectorielle dédiée est plus simple à opérer et mieux intégrée aux nodes Vector Store de n8n. Une bonne partie des cas réels finissent en recherche hybride.

Bundle FlowKit Complet

269 €