<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[ES|QL - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[ES|QL - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/fr/search-labs/blog/category/esql</link>
    </image>
    <link>https://www.elastic.co/fr/search-labs/blog/category/esql</link>
    <atom:link href="https://www.elastic.co/fr/search-labs/rss/category/esql.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[fr]]></language>
    <lastBuildDate>Tue, 29 Sep 2026 09:34:13 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Elasticsearch ES|QL permet d'effectuer des recherches full-text sur des données que vous n'avez jamais indexées]]></title>
    <description><![CDATA[Les fonctions MATCH et TO_TEXT permettent d'effectuer une recherche full-text sur des données que vous n'avez jamais indexées. Effectuez des recherches sur des colonnes calculées, des champs non mappés et des sources fédérées avec ES|QL.]]></description>
    <content:encoded><![CDATA[<p>La fonction MATCH d'ES|QL permet désormais d'effectuer des recherches full-text sur des données que vous n'avez jamais indexées, y compris les colonnes calculées, les champs non mappés, les chaînes assemblées à la volée et même les données fédérées stockées dans S3. La nouvelle fonction TO_TEXT indique à ES|QL de traiter n'importe quelle chaîne comme du texte analysable ; MATCH peut ainsi générer des tokens, normaliser la casse et mettre en correspondance des termes avec des valeurs qui n'existent que le temps de la requête. Il s'agit d'une véritable analyse, qui va bien au-delà de la correspondance de patterns via LIKE et RLIKE proposée par la plupart des moteurs de requête pour les chaînes non indexées. Disponible dès maintenant sur Elastic Cloud Serverless et en préversion technique dans Elasticsearch 9.5.</p><h2>Comment MATCH et TO_TEXT permettent la recherche full-text sur n'importe quelle expression ES|QL</h2><p>Commençons par une requête qui était impossible dans Elasticsearch 9.4, qui utilise <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/eval">la commande EVAL</a> :</p><p>Dans cet exemple, le résumé ne dispose d'aucune configuration de mapping ou d'analyseur. Il n'est pas non plus associé à un index inversé. Il n'existe que le temps de cette requête, mais il est tout de même possible d'effectuer des recherches dessus. Deux ajouts permettent d'y parvenir.</p><p>Premièrement, la fonction <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/search-functions/match">MATCH</a> accepte désormais n'importe quelle expression comme premier argument, et non plus seulement un champ mappé. Cela inclut les colonnes générées par EVAL ainsi que les résultats de fonctions utilisés directement dans l'expression. Cela englobe également les champs non mappés chargés directement depuis le document d'origine. De plus, tous les types de données habituellement acceptés par MATCH sont compatibles avec ce nouveau cas d'utilisation.</p><p>Deuxièmement, la nouvelle fonction <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/type-conversion-functions/to_text">TO_TEXT</a>, qui est la première fonction de conversion ES|QL qui produit une sortie de type texte. Jusqu'à présent, les colonnes de texte ne pouvaient provenir que de champs mappés indexés, et toutes les chaînes générées par les expressions ES|QL étaient des valeurs de mots-clés plutôt que de texte. Cette distinction est importante car MATCH traite les deux différemment : les valeurs de texte sont analysées, tandis que les valeurs de mots-clés sont comparées exactement, reproduisant ainsi le mécanisme par lequel une requête MATCH sur un champ de mot-clé indexé est réécrite en requête de terme. TO_TEXT(x) permet d'indiquer à ES|QL de <em>traiter cette chaîne comme du texte intégral</em>.</p><p>Cette fonctionnalité est disponible en préversion technique dans Elasticsearch 9.5, et, à ce titre, présente certaines limitations :</p><ul><li><p>Pour l'instant, elle se limite au filtrage. Une opération MATCH portant sur une expression ne contribue pas encore au score de pertinence ; seuls les matchs sur des champs indexés influencent ce score.</p></li><li><p>Les options de requête telles que la tolérance aux erreurs ne sont pas encore prises en charge lors de l'utilisation de MATCH sur une expression.</p></li><li><p>Le texte généré à l'exécution est analysé à l'aide de l'analyseur standard. Ce comportement n'est pas encore configurable.</p></li></ul><p>Ces limitations seront résolues prochainement.</p><h2>Pourquoi utiliser la recherche full-text plutôt que LIKE ou RLIKE dans ES|QL ?</h2><p>ES|QL disposait déjà de deux méthodes pour rechercher des chaînes de caractères sans index : LIKE (caractères génériques) et RLIKE (expressions régulières). Les deux fonctionnant sur n'importe quelle expression de chaîne, on peut donc se demander ce que MATCH apporte. La réponse est l'<a href="https://www.elastic.co/docs/manage-data/data-store/text-analysis">analyse</a>, une forme plus avancée de recherche qui utilise des techniques telles que la lemmatisation et les synonymes. Elle intègre également la gestion des mots vides.</p><p>LIKE effectue une simple correspondance de sous-chaîne, sans aucune compréhension des mots qui composent la chaîne. Supposons, par exemple, que vous recherchiez des messages de log à propos d'un renard :</p><p>La correspondance "Fox spotted near the henhouse" n'est pas détectée en raison de la majuscule, alors que la correspondance "Outfoxed by the competition", qui n'a aucun rapport avec un renard, est détectée. Le système échoue dans les deux cas : faux négatifs liés à la casse et faux positifs dus à des sous-chaînes incluses dans d'autres mots.</p><p>Les expressions régulières peuvent résoudre le problème de la casse, mais la gestion des limites de mots devient vite complexe. Quelque chose comme :</p><p>Et même là, ce n'est pas encore tout à fait ça. L'expression ne détecte pas le mot "fox" en fin de phrase s'il est suivi d'un point d'exclamation ou d'interrogation, et elle ne tient pas compte des tabulations, des guillemets ou des parenthèses. Chaque correction allonge le pattern, obligeant la personne suivante qui lira la requête à procéder à une ingénierie inverse pour comprendre ce qu'elle fait réellement.</p><p>MATCH résout le problème, car il fait passer aussi bien la requête que la valeur par un <a href="https://www.elastic.co/docs/reference/text-analysis/analyzer-reference">analyseur</a> qui découpe le texte à l'aide de tokens et le convertit en minuscules, puis compare les termes entre eux :</p><p>Cette requête correspondra à des valeurs comme "The quick brown fox" et "FOX spotted near the henhouse", mais pas à "Outfoxed by the competition" ou "FOXTROT protocol enabled", quelle que soit la ponctuation entourant les mots. Bien entendu, tout cela fonctionne également pour les requêtes comportant plusieurs termes, comme MATCH(TO_TEXT(message), "brown fox"), exactement comme on peut s'y attendre.</p><p>Des travaux sont en cours pour permettre l'utilisation des <a href="https://www.elastic.co/docs/reference/text-analysis/analysis-lang-analyzer">36 analyseurs linguistiques dédiés</a>, avec la prise en charge des langues naturelles sur des données jamais indexées ni mappées.</p><h2>Cas d'utilisation de la recherche full-text pour des données non indexées et non mappées</h2><p>Les exemples ci-dessus portaient sur des valeurs calculées à partir de <a href="https://www.elastic.co/docs/manage-data/data-store/mapping">champs mappés</a>. Les cas d'utilisation les plus intéressants de la fonction MATCH d'ES|QL appliquée à des expressions concernent des données qui, auparavant, n'étaient pas du tout interrogeables. Examinons quelques-uns de ces cas.</p><h3>Comment rechercher des champs non mappés dans ES|QL sans ajouter de mapping</h3><p>Il arrive parfois que l'on doive exclure un champ de nos mappings, comme une trace de pile détaillée ou une charge utile de requête brute. On peut même omettre un blob à déboguer. L'indexation de l'un de ces éléments consommerait de l'espace disque et de la mémoire pour chaque document, ce qui ne se justifierait pas pour un champ que l'on n'interroge peut-être qu'une fois par trimestre.</p><p>Cette décision a toujours été irrévocable, car les <a href="https://www.elastic.co/search-labs/blog/esql-unmapped-fields">champs non mappés</a> étaient totalement invisibles pour les requêtes. Dans Elasticsearch 9.5, vous pouvez utiliser SET unmapped_fields="load" pour permettre à ES|QL de charger directement les champs non mappés depuis le document source en tant que mots-clés. En enveloppant ensuite le résultat dans TO_TEXT, vous pouvez exécuter une recherche full-text sur ces champs :</p><p>Ici, stack_trace n'a jamais été mappé. Chaque valeur est récupérée depuis les documents d'origine et analysée à la volée ; la correspondance est établie ligne par ligne. C'est un travail conséquent, qui ne sera jamais aussi rapide qu'une recherche via un <a href="https://www.elastic.co/docs/manage-data/data-store/index-basics">index inversé</a>. Toutefois, ce champ que vous n'aviez pas indexé n'est plus impossible à interroger. Vous pouvez ainsi conserver un mapping léger pour les besoins courants tout en étant capable de répondre, le moment venu, à une question qui ne se pose qu'une fois par trimestre.</p><h3>Recherche full-text sur un champ de mots-clés sans réindexation</h3><p>Les champs de mots-clés offrent de nombreuses possibilités. Ils permettent une correspondance exacte, des agrégations rapides et le tri des données ; c'est pourquoi tant de champs sont finalement mappés de cette manière. Toutefois, le mapping est défini au moment de l'arrivée des données, et il est fréquent de se retrouver dans une situation où l'on souhaite exploiter ces données différemment de ce qui avait été prévu initialement. Par exemple, le champ product_name a peut-être été mappé en tant que mot-clé parce que les tableaux de bord s'appuyaient sur lui pour des agrégations. Or, après avoir accumulé une année de données produits, un utilisateur peut soudainement vouloir effectuer des recherches au sein même des valeurs de ce champ.</p><p>L'ancienne solution consiste à convertir le mapping en texte (ou à ajouter un champ multiple) et à tout réindexer. Cette opération est longue et coûteuse et, bien souvent, les utilisateurs ne veulent pas s'en donner la peine. La nouvelle solution se résume à un seul appel de fonction :</p><p>TO_TEXT convertit à la volée les valeurs de mot-clés en texte, permettant ainsi à MATCH de les analyser plutôt que de les comparer de manière exacte. Cela vous permet d'interroger un champ de mot-clé sans avoir à créer de mapping ni à réindexer le document source. Si cette recherche est amenée à devenir une requête courante, l'indexation du champ en tant que texte reste la solution idéale à long terme. Toutefois, TO_TEXT vous permet d'obtenir une réponse immédiate, sans travail supplémentaire.</p><h3>Recherche sur le même champ dans des index aux mappings différents</h3><p><a href="https://www.elastic.co/docs/reference/query-languages/esql/esql-multi-index">ES|QL peut couvrir plusieurs index</a>, et un même champ ne doit pas nécessairement présenter la même structure dans chacun d'eux. Lorsqu'un même champ possède des types différents selon les index, ES|QL le traite comme un type d'union, et une fonction de conversion résout le conflit. Prenons l'exemple d'un champ de message qui est de type texte dans le modèle d'index de cette année, alors qu'il était de type mot-clé dans celui de l'année précédente :</p><p>Chaque valeur est analysée au moment de la requête, qu'elle provienne de l'index texte ou de l'index mots-clés. Les valeurs de type mot-clé issues des anciens index sont découpées en tokens et converties en minuscules, tout comme les autres ; ainsi, la recherche "connection reset" permet de trouver "Connection RESET by peer", quel que soit l'index dans lequel la donnée est stockée.</p><p>Un autre cas intéressant est celui où un champ est mappé dans un seul index mais également présent (et non mappé) dans l'autre :</p><p>Il existe une nuance ici qu'il convient de souligner. Si error_details est mappé dans logs-2026 mais pas dans logs-2025, Elasticsearch ne peut pas déléguer cette requête à <a href="https://lucene.apache.org/">Lucene</a>, car les index où le champ n'est pas mappé ne renverraient silencieusement aucun résultat. Au lieu de cela, le planificateur détecte que le champ n'est potentiellement pas mappé et évalue l'intégralité de la clause MATCH ligne par ligne, quelle que soit la provenance des lignes. Vous n'avez pas besoin de savoir à quels index appartient le mapping de ce champ ; la requête répond simplement à la question.</p><h2>Comment ES|QL analyse le texte au moment de la requête sans index inversé</h2><p>Lorsque ES|QL planifie une opération MATCH sur une expression, il analyse la chaîne de requête une seule fois, au préalable, pour la transformer en un ensemble de termes. La manière dont chaque ligne est ensuite évaluée dépend du type de l'expression :</p><p><strong>Type d'expression</strong></p><p><strong>Traitement</strong></p><p><strong>Comportement correspondant</strong></p><p>texte (via TO_TEXT)</p><p>L'analyseur segmente la valeur à l'aide de tokens et la convertit en minuscules</p><p>Comparaison token par token ; une ligne correspond si un token correspond à un terme de requête quelconque (sémantique OU)</p><p>mot-clé, adresse IP, date, numérique</p><p>Aucune analyse ; constante de la requête convertie une seule fois vers le type natif</p><p>Comparaison exacte par ligne</p><p>Ces deux méthodes contournent entièrement Lucene et évaluent les valeurs ligne par ligne. Le chemin non textuel reproduit exactement le comportement d'une requête de correspondance lorsqu'elle est déléguée à Lucene pour ces types de champs ; la sémantique reste donc cohérente, que la requête utilise un index ou non.</p><p>Une recherche via un index inversé s'effectue au moment de l'ingestion et n'interagit jamais avec les documents non correspondants lors de l'exécution de la requête. À l'inverse, une opération MATCH effectuée à l'exécution réalise cette analyse au moment de la requête, pour chaque ligne traitée. La première méthode est rapide car le travail a déjà été accompli en amont, tandis que la seconde offre de la flexibilité, car les données n'ont pas besoin d'avoir été indexées au préalable.</p><h2>Prochaines évolutions de la recherche full-text dans ES|QL</h2><p>Tout ce qui est présenté dans cet article constitue la première étape d'une initiative plus vaste visant à permettre à la recherche ES|QL de fonctionner sur n'importe quelles données, et pas seulement sur celles indexées au préalable. Nous travaillons activement à lever les limitations mentionnées précédemment, et la roadmap va encore plus loin :</p><ul><li><p><strong>Calcul du score.</strong> Les correspondances évaluées à l'exécution contribueront au score (_score) ; vous pourrez ainsi effectuer un tri par pertinence, même si les données n'ont jamais été indexées.</p></li><li><p><strong>MATCH_PHRASE</strong><strong> sur les expressions.</strong> Déjà disponible dans Elastic Cloud Serverless et prochainement dans la Suite Elastic version 9.6.</p></li><li><p><strong>Analyseurs configurables.</strong> Prise en charge des analyseurs pour MATCH et MATCH_PHRASE sur les expressions, permettant l'utilisation d'analyseurs linguistiques, de la lemmatisation et de synonymes au moment de la requête.</p></li><li><p><strong>Options de correspondance.</strong> Des options telles que la tolérance et l'opérateur pour les correspondances à l'exécution.</p></li><li><p><strong>Recherche vectorielle.</strong> Génération d'embeddings par ligne et exécution de l'algorithme des k plus proches voisins (kNN) sur des expressions dense_vector évaluées à l'exécution, permettant d'étendre la recherche sémantique aux données non indexées.</p></li></ul><h2>Essayez dès aujourd'hui la recherche full-text ES|QL sur les expressions</h2><p>Vous pouvez essayer la recherche au moment de l'exécution dès maintenant. Elle est disponible dans Elastic Cloud Serverless, où les nouvelles fonctionnalités ES|QL sont déployées en priorité, et proposée en préversion technique dans Elasticsearch 9.5. Commencez par consulter la documentation de référence sur les <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/search-functions">fonctions de recherche</a> ainsi que les limites actuelles sur la page dédiée aux <a href="https://www.elastic.co/docs/reference/query-languages/esql/limitations">limitations ES|QL</a>. Cette préversion technique est destinée à recueillir votre avis : si vous effectuez une recherche sur un élément qui n'a jamais été indexé et que le résultat vous surprend – en bien ou en mal –, <a href="https://www.elastic.co/fr/community">n'hésitez pas à nous en faire part</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/full-text-search-unindexed-data</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/full-text-search-unindexed-data</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[Mappings]]></category>
    <dc:creator><![CDATA[Kevin Corcoran,Ioana Tagirta]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9a74e633d05585a8/6a730774b8c2e64c3ebe0fd4/image1.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Du prompt au tableau de bord en moins d'une minute, pour un coût divisé par 5 : tableaux de bord IA et graphiques Vega-Lite personnalisés dans Kibana]]></title>
    <description><![CDATA[Décrivez vos métriques en langage naturel ; le chat IA de Kibana génère des tableaux de bord et des graphiques Vega-Lite basés sur ES|QL, allant des nuages de points à la mise en forme conditionnelle et aux infobulles personnalisées.]]></description>
    <content:encoded><![CDATA[<p>Le <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/chat">chat IA</a> de Kibana crée désormais des tableaux de bord complets <a href="https://www.elastic.co/docs/explore-analyze/visualize/esorql">basés sur le langage de requête Elasticsearch (ES|QL)</a> à partir d'un prompt en langage naturel, en moins d'une minute. Dans la version Elastic 9.5, cette fonctionnalité passe au stade de disponibilité générale (DG) (<a href="https://www.elastic.co/fr/search-labs/blog/ai-dashboard-generation-elastic-agent-kibana">en préversion technique 9.4</a>) et intègre un mécanisme de récupération des erreurs qui relance les requêtes ayant échoué, réduit par cinq les coûts de génération ES|QL grâce au routage hiérarchisé des modèles et propose des contrôles de filtrage interactifs. Cette version ajoute également la création de graphiques <a href="https://www.elastic.co/docs/explore-analyze/visualize/custom-visualizations-with-vega">Vega-Lite</a> en langage naturel, incluant des nuages de points, des diagrammes en boîte, une mise en forme conditionnelle et des infobulles personnalisées, autant d'éléments qu'il fallait auparavant coder manuellement en JSON.</p><h2>Quoi de neuf dans la création de tableaux de bord IA avec Kibana</h2><p><strong>Fonctionnalité</strong></p><p><strong>Préversion technique (9.4)</strong></p><p><strong>DG (9.5)</strong></p><p>Gestion des erreurs</p><p>Pas de nouvelle tentative en cas d'échec des requêtes ES|QL</p><p>Jusqu'à trois tentatives automatiques avec inspection et ajustement des requêtes</p><p>Coût de génération ES|QL</p><p>Toutes les requêtes sont acheminées via le modèle principal</p><p>Modèle de routage à plusieurs niveaux, jusqu'à 5 fois moins cher</p><p>Plage temporelle</p><p>Fenêtre fixe par défaut</p><p>Sélection automatique en fonction de la distribution temporelle des données</p><p>Contrôles de filtre</p><p>Non pris en charge</p><p>Ajoutés automatiquement pour les champs les plus pertinents</p><p>Graphiques Vega-Lite</p><p>Non pris en charge</p><p>Création en langage naturel, incluant les nuages de points, les diagrammes en boîte, la mise en forme conditionnelle et les infobulles personnalisées</p><p>Modification de graphique</p><p>Non pris en charge</p><p>Modification des panneaux Vega-Lite existants en langage naturel</p><h3>Récupération automatique des erreurs pour la génération de tableaux de bord par IA</h3><p>Dans la préversion technique, l'agent ne relançait pas les requêtes ES|QL ayant échoué. Avec la version 9.5, il détecte les erreurs de requête et tente de les réexécuter jusqu'à trois fois ; il analyse chaque erreur et ajuste la requête avant d'abandonner. En pratique, cela élimine la majeure partie des problèmes de panneaux vides et permet d'obtenir des tableaux de bord qui s'affichent correctement dès la première tentative.</p><h3>Pourquoi la création de tableaux de bord par IA est-elle moins coûteuse dans Elastic 9.5 ?</h3><p>Les étapes de génération d'un tableau de bord ne nécessitent pas toutes le même niveau de raisonnement. Dans la version 9.5, la génération ES|QL passe par un modèle plus léger par défaut et revient au modèle principal uniquement en cas de besoin. Si votre <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/connectors">connecteur</a> utilise Claude Opus 4.8 d'Anthropic, la génération ES|QL pour tous les panneaux revient alors cinq fois moins cher.</p><h3>Sélection automatique de la plage temporelle basée sur vos données</h3><p>Les tableaux de bord ne sont utiles que s'ils affichent la fenêtre de données appropriée. L'agent applique désormais une logique optimisée pour sélectionner une période pertinente au regard des données interrogées, à moins que l'utilisateur ne spécifie une plage horaire particulière. Il prend en compte la répartition temporelle des données et adapte son choix en conséquence, qu'il s'agisse de la dernière heure pour un incident en cours ou des 90 derniers jours pour une analyse de tendance, plutôt que de s'en tenir systématiquement à une fenêtre temporelle fixe.</p><h3>Contrôles de filtrage automatiques sur les tableaux de bord générés par IA</h3><p>La création de tableaux de bord prend désormais en charge les contrôles, c'est-à-dire des filtres interactifs qui permettent aux utilisateurs d'affiner un tableau de bord en fonction des valeurs des champs sans modifier les requêtes sous-jacentes. Lors de la génération d'un tableau de bord, l'agent ajoute automatiquement des contrôles en haut pour les champs les plus pertinents à filtrer.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4a5520e66ae76001/6a719a218a155220ed6498e7/image3.png" alt="Kibana AI chat generating an ES|QL-backed host metrics dashboard with automatic filter controls in 71 seconds" /><h2>Graphiques Vega-Lite à partir du langage naturel : types de graphiques et mise en forme au-delà des valeurs par défaut</h2><p><a href="https://vega.github.io/vega/">Vega</a> et <a href="https://vega.github.io/vega-lite/examples/">Vega-Lite</a> prennent en charge une grande variété de types de graphiques et de personnalisations dans Kibana. Avec la version 9.5, vous pouvez les créer en langage clair au lieu d'écrire le code vous-même. </p><h3>Nuages de points, diagrammes en boîte et autres types de graphiques Vega-Lite</h3><p>Les nuages de points, les diagrammes en boîte, les graphiques à facettes, les graphiques à bulles et les graphiques de composition (tels que la combinaison d'histogrammes et de cartes thermiques), entre autres, sont pris en charge par <a href="https://vega.github.io/vega-lite/examples/">Vega-Lite</a>. Un prompt comme <em>Affiche-moi un nuage de points du temps de réponse en fonction de la taille de la requête, avec une coloration par nom de service</em> génère un panneau Vega-Lite intégrant les mappings de données appropriés. Ces graphiques utilisent les palettes de couleurs par défaut de Kibana afin de s'harmoniser avec le reste du tableau de bord.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf1651fe7ac903d47/6a719a49f124649f746fc1b4/image5.png" alt="Kibana dashboard with four Vega-Lite charts: box plot, bubble chart, faceted small multiples, and heatmap." /><h3>Mise en forme conditionnelle, infobulles personnalisées et étiquettes sur graphiques standard</h3><p>Même pour les types de graphiques déjà intégrés dans les tableaux de bord comme les graphiques à barres, linéaires ou en aires, il est parfois nécessaire de disposer d'un contrôle plus poussé que celui offert par les fonctionnalités par défaut. Vega-Lite permet de combler cette lacune via le chat. En voici quelques exemples :</p><ul><li><p><strong>Mise en forme conditionnelle des couleurs</strong> : appliquez une couleur différente aux points de données dépassant un certain seuil ; par exemple, colorez en rouge les points d'un graphique linéaire ou en barres lorsqu'une métrique dépasse votre objectif de niveau de service (SLO). Demandez à l'agent quelque chose comme <em>Colore en rouge tous les points dépassant 500 ms sur mon graphique linéaire.</em> </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc1211784e9033557/6a719a6ab966e1736163d7d1/image1.png" alt="Vega-Lite line and bar charts in Kibana with conditional colour formatting showing data points above a threshold in red" /><p></p></li><li><p><strong>Marqueurs et étiquettes personnalisés</strong> : ajoutez des émojis, des symboles ou des étiquettes textuelles intégrées aux points de données pour obtenir des indicateurs d'état visibles d'un seul coup d'œil.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3c59c3748484bc1/6a719aa02888394fdc07bac1/image2.png" alt="Lite horizontal bar chart in Kibana with emoji flag labels and custom tooltip showing requests by country" /><p></p></li><li><p><strong>Infobulles personnalisées</strong> : enrichissez les états au survol avec des métriques supplémentaires, du contexte ou des valeurs calculées qui ne figurent pas sur les axes du graphique. Demandez par exemple <em>Ajoute une infobulle indiquant le nombre total d'enregistrements et le pourcentage par barre.</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt43f241f4382b5b90/6a719ab7ded0cf3367f49275/image4.png" alt="Vega-Lite stacked bar chart in Kibana with custom tooltip showing total records and percentage of total by extension" /><p></p></li></ul><p>Cette méthode fonctionne également pour modifier des graphiques Vega existants. Si vous avez un panneau Vega-Lite nécessitant une retouche comme modifier une échelle de couleurs, ajuster un axe ou changer le type de marqueur, décrivez la modification dans le chat plutôt que de fouiller dans le code JSON.</p><h2>Comment nous avons créé la génération Vega-Lite en langage naturel dans Kibana</h2><p>Générer un graphique Vega-Lite à partir d'une phrase ne se résume pas à un simple prompt unique <em>demandant au modèle de fournir du JSON</em>. Nous avons mis au point un petit pipeline de type agent capable de transformer une intention exprimée en langage naturel en un graphique validé et étayé par des données.</p><p>À la réception d'une requête, l'agent détermine d'abord si Vega-Lite est la solution appropriée. Pour les requêtes Vega-Lite, il ancre la visualisation sur une véritable requête ES|QL adressée à Elasticsearch, puis utilise un modèle pour générer le code Vega-Lite. Avant le rendu, le résultat passe par une couche de normalisation qui corrige le schéma et lie la requête canonique ; des transformations visant à garantir la sécurité du rendu sont également appliquées. </p><p>Quelques choix de conception rendent ce workflow fiable :</p><ul><li><p><strong>Appel d'outil typé</strong> : la création de graphiques repose sur l'appel structuré d'un outil plutôt que sur l'insertion de code Vega-Lite en format libre dans la conversation.</p></li><li><p><strong>Génération contrainte</strong> : le modèle génère du code Vega-Lite selon un schéma défini, ce qui rend la sortie plus prévisible et plus facile à valider.</p></li><li><p><strong>Exemples sélectionnés</strong> : les schémas structurels, tels que la navigation à facettes, les marqueurs superposés et les cartes thermiques, fournissent des indications sans copier les données sous-jacentes.</p></li><li><p><strong>Boucles d'exécution et de vérification</strong> : les requêtes sont exécutées avant la création du graphique, et les échecs de validation déclenchent des tentatives correctives pour la génération ES|QL.</p></li></ul><h2>Essayez la création de tableaux de bord par IA et les graphiques Vega-Lite dans Kibana</h2><p>Pour tester la création de tableaux de bord en langage naturel et les graphiques Vega-Lite, passez à <strong>Elastic 9.5</strong> (ou <a href="https://cloud.elastic.co/registration">commencez un essai gratuit</a>) et ouvrez le <strong>chat</strong> dans Kibana. Demandez ensuite à l'outil de générer un tableau de bord à partir de vos données. Pour Vega-Lite, demandez un type de graphique que vous avez toujours voulu mais que vous n'avez jamais créé, comme un nuage de points ou un graphique à bulles. Si le résultat ne vous convient pas tout à fait, indiquez à l'agent ce qu'il faut modifier ; il itère avec vous.</p><p>Cela nécessite une licence Entreprise. <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/chat#get-started">Commencer</a>.</p><p><em>La publication et la date de publication de toute fonctionnalité ou fonction décrite dans le présent article restent à la seule discrétion d'Elastic. Toute fonctionnalité ou fonction qui n'est actuellement pas disponible peut ne pas être livrée à temps ou ne pas être livrée du tout.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-dashboards-kibana-vega-lite</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-dashboards-kibana-vega-lite</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Marta Bondyra,Teresa Alvarez Soler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt54406ad0378bc5fc/6a7199ffed03ccee0dac9d7c/image6.png" length="0" type="image/png"/>
    <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[LINQ to Elasticsearch ES|QL : écrire en C#, interroger Elasticsearch]]></title>
    <description><![CDATA[Découverte du nouveau fournisseur LINQ to Elasticsearch ES|QL dans le client Elasticsearch .NET, qui vous permet d'écrire du code C# qui est automatiquement converti en requêtes ES|QL.]]></description>
    <content:encoded><![CDATA[<p>À partir des versions <strong>9.3.4</strong> et <strong>8.19.18</strong>, le client .NET Elasticsearch inclut un fournisseur <a href="https://learn.microsoft.com/en-us/dotnet/csharp/linq/">LINQ (Language Integrated Query) </a>qui traduit les expressions LINQ C# en <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html">requêtes ES|QL (Elasticsearch Query Language)</a> à l'exécution. Au lieu d'écrire manuellement des chaînes ES|QL, vous composez vos requêtes à l'aide des fonctions <code>Where</code>, <code>Select</code>, <code>OrderBy</code>, <code>GroupBy</code> et d'autres opérateurs standard. Le fournisseur se charge de la traduction, du paramétrage et de la désérialisation des résultats, y compris le flux par ligne qui maintient l'utilisation de la mémoire constante, quelle que soit la taille de l'ensemble des résultats.</p><h2>Votre première requête</h2><p>Commencez par définir un objet CLR (POCO) classique qui correspond à votre index Elasticsearch. Les noms de propriétés sont résolus en noms de colonnes ES|QL via des attributs standard <code>System.Text.Json</code>, comme <code>[JsonPropertyName]</code>, ou via un <code>JsonNamingPolicy</code> configuré. Les mêmes règles de <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/source-serialization">sérialisation des sources</a> que celles qui s'appliquent au reste du client s'appliquent également ici.</p>using System.Text.Json.Serialization;

public class Product
{
    [JsonPropertyName("product_id")]
    public string Id { get; set; }

    public string Name { get; set; }

    public string Brand { get; set; }

    [JsonPropertyName("price_usd")]
    public double Price { get; set; }

    [JsonPropertyName("in_stock")]
    public bool InStock { get; set; }
}<p>Une fois le type défini, une requête ressemble à ceci :</p>var minPrice = 100.0;
var brand = "TechCorp";

await foreach (var product in client.Esql.QueryAsync&lt;Product&gt;(q =&gt; q
    .From("products")
    .Where(p =&gt; p.InStock &amp;&amp; p.Price &gt;= minPrice &amp;&amp; p.Brand == brand)
    .OrderByDescending(p =&gt; p.Price)
    .Take(10)))
{
    Console.WriteLine($"{product.Name}: ${product.Price}");
}<p>Le fournisseur la traduit en ES|QL comme ceci :</p><p>Quelques détails à noter :</p><ul><li><p><strong>Résolution des noms de propriété</strong> : <code>p.Price</code> devient <code>price_usd</code> en raison de l'attribut <code>[JsonPropertyName]</code>, et <code>p.Brand</code> devient <code>brand</code> conformément à la politique de dénomination camelCase par défaut.</p></li><li><p><strong>Capture des paramètres</strong> : les variables C# <code>minPrice</code> et <code>brand</code> sont capturées comme paramètres nommés (<code>?minPrice</code>, <code>?brand</code>). Elles sont envoyées séparément de la chaîne de requête dans la charge utile JSON, ce qui empêche l'injection et permet la mise en cache du plan de requête côté serveur.</p></li><li><p><strong>Flux en continu</strong> : <code>QueryAsync&lt;T&gt;</code> renvoie <code>IAsyncEnumerable&lt;T&gt;</code>. Les lignes se matérialisent une à une à mesure de leur arrivée depuis Elasticsearch.</p></li></ul><p>Vous pouvez également inspecter la requête générée et ses paramètres sans l'exécuter :</p>var query = client.Esql.CreateQuery&lt;Product&gt;()
    .Where(p =&gt; p.InStock &amp;&amp; p.Price &gt;= minPrice &amp;&amp; p.Brand == brand)
    .OrderByDescending(p =&gt; p.Price)
    .Take(10);

Console.WriteLine(query.ToEsqlString());
// FROM products | WHERE (in_stock == true AND price_usd &gt;= 100) | SORT price_usd DESC | LIMIT 10

Console.WriteLine(query.ToEsqlString(inlineParameters: false));
// FROM products | WHERE (in_stock == true AND price_usd &gt;= ?minPrice AND brand == ?brand) | SORT price_usd DESC | LIMIT 10

var parameters = query.GetParameters();
// { "minPrice": 100.0, "brand": "TechCorp" }<h2>Comment ça marche ? Petit rappel sur LINQ</h2><p>Le mécanisme qui rend possibles les fournisseurs LINQ est la distinction entre <code>IEnumerable&lt;T&gt;</code> et <code>IQueryable&lt;T&gt;</code>.</p><p>Lorsque vous appelez <code>.Where(p =&gt; p.Price &gt; 100)</code> sur un <code>IEnumerable&lt;T&gt;</code>, la lambda est compilée en un <code>Func&lt;Product, bool&gt;</code>, un délégué standard que le runtime exécute en interne. C'est le principe du LINQ-to-Objects.</p><p>Lorsque vous appelez la même méthode sur un <code>IQueryable&lt;T&gt;</code>, le compilateur C# enveloppe la lambda dans un <code>Expression&lt;Func&lt;Product, bool&gt;&gt;</code> à la place. Il s'agit d'une structure de données qui représente la <em>structure</em> du code plutôt que sa forme exécutable. L'arbre d'expression peut être inspecté, analysé et traduit dans un autre langage au moment de l'exécution.</p>// IEnumerable: the lambda is a compiled delegate
IEnumerable&lt;Product&gt; local = products.Where(p =&gt; p.Price &gt; 100);

// IQueryable: the lambda is an expression tree, a data structure
IQueryable&lt;Product&gt; remote = queryable.Where(p =&gt; p.Price &gt; 100);<p>L’interface <code>IQueryProvider</code> est le point d’extension. Tout fournisseur peut implémenter <code>CreateQuery&lt;T&gt;</code> et <code>Execute&lt;T&gt;</code> pour traduire ces arbres d’expressions dans une langue cible. Entity Framework utilise ceci pour émettre du SQL. Le fournisseur LINQ to ES|QL l'utilise pour émettre ES|QL.</p><p>L'arbre d'expression de la requête ci-dessus ressemble à ceci :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt521838e8b9c36649/6a1705b1839dfa5f40dcfdfe/f864cd18a390831f8d28503a29b5835efb1842f7-1000x720.png" alt="Arbre d'expression de l'exemple de requête." /><p><em>Arbre d'expression de l'exemple de requête.</em></p><p>L'arbre est imbriqué de l'intérieur vers l'extérieur : <code>Take</code> englobe <code>OrderByDescending</code>, qui englobe <code>Where</code>, qui englobe <code>From</code>, qui englobe la racine constante <code>EsqlQueryable&lt;Product&gt;</code>. Le prédicat <code>Where</code> est lui-même un sous-arbre des nœuds <code>BinaryExpression</code> pour les opérateurs <code>&amp;&amp;</code>, <code>&gt;=</code>, et les opérateurs <code>==</code>, avec des feuilles <code>MemberExpression</code> pour les accès aux propriétés et des captures de fermeture pour les variables <code>minPrice</code> et <code>brand</code>. C'est cette structure de données que le fournisseur parcourt pour produire le code ES|QL final.</p><h2>Sous le capot : le pipeline de traduction</h2><p>Le chemin d'une expression LINQ vers les résultats de la requête suit un pipeline en six étapes :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt930670a505dd61ea/6a1705b3b339d58a54769ecf/2a2c772b63d720f61fc9a28b2f85668fa2db8d38-1999x1036.png" alt="Aperçu du pipeline de traduction." /><p><em>Aperçu du pipeline de traduction.</em></p><h3>1. Capture de l'arbre d'expressions</h3><p>Lorsque vous chaînez <code>.Where()</code>, <code>.OrderBy()</code>, <code>.Take()</code> et d’autres opérateurs sur un <code>IQueryable&lt;T&gt;</code>, l’infrastructure standard de LINQ construit un arbre d’expressions. <code>EsqlQueryable&lt;T&gt;</code> met en œuvre <code>IQueryable&lt;T&gt;</code> et délègue à <code>EsqlQueryProvider</code>.</p><h3>2. Traduction</h3><p>Lors de l'exécution de la requête (par énumération, appel de <code>ToList()</code> ou utilisation de <code>await foreach)</code>), le <code>EsqlExpressionVisitor</code> parcourt l'arbre d'expressions de l'intérieur vers l'extérieur. Il envoie chaque appel de méthode LINQ à un visiteur spécialisé :</p><p>Visiteur</p><p>Est traduit</p><p>En</p><p>WhereClauseVisitor</p><p>.Where(predicate)</p><p>Condition WHERE</p><p>SelectProjectionVisitor</p><p>.Select(selector)</p><p>EVAL + KEEP + RENAME</p><p>GroupByVisitor</p><p>.GroupBy().Select()</p><p>STATS ... BY</p><p>OrderByVisitor</p><p>.OrderBy() / .ThenBy()</p><p>Champ SORT [ASC\|DESC]</p><p>EsqlFunctionTranslator</p><p>EsqlFunctions.*, Math.*, méthodes string</p><p>Plus de 80 fonctions ES|QL</p><p>Lors de la traduction, les variables C# référencées dans les expressions sont capturées comme des paramètres nommés.</p><h3>3. Modèle de requête</h3><p>Les visiteurs ne produisent pas directement des chaînes de caractères. À la place, ils produisent des objets <code>QueryCommand</code> , une représentation intermédiaire immuable. Un objet <code>FromCommand</code>, un objet <code>WhereCommand</code>, un objet <code>SortCommand</code> et un objet <code>LimitCommand</code>, chacun représentant une commande de traitement ES|QL. Ces objets sont ensuite regroupés dans un modèle <code>EsqlQuery</code>.</p><p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt788c9936976f2f62/6a1705b50e2e4910da419ff0/2adc349b6cf655b96b7b3e826a134e8a17fe42fd-1999x1036.png" alt="Modèle de requête et schéma de commande." /><p><em>Modèle de requête et schéma de commande.</em></p><p>Ce modèle intermédiaire est découplé de l'arbre d'expression et du format de sortie. Il peut être inspecté, intercepté (via <code>IEsqlQueryInterceptor</code>) ou modifié avant d'être formaté.</p><h3>4. Formatage</h3><p><code>EsqlFormatter</code> parcourt chaque <code>QueryCommand</code> dans l'ordre et produit la chaîne ES|QL finale. Chaque commande devient une ligne, séparée par l'opérateur pipe (|) utilisé par ES|QL pour chaîner les commandes de traitement. Les identificateurs contenant des caractères spéciaux sont automatiquement échappés par des guillemets inversés.</p><h3>5. Exécution</h3><p>La chaîne ES|QL formatée et les paramètres capturés sont envoyés au point de terminaison <code>/_query</code> d'Elasticsearch sous forme de charge utile JSON. L'interface <code>IEsqlQueryExecutor</code> masque la couche transport, où l'architecture de packages en couches prend tout son sens.</p><h3>6. Matérialisation</h3><p><code>EsqlResponseReader</code> transmet la réponse JSON sans mettre en mémoire tampon l'ensemble des résultats. Un arbre <code>ColumnLayout</code>, précalculé une fois par requête, mappe les noms de colonnes ES|QL plats (comme <code>address.street</code>, <code>address.city</code>) aux propriétés POCO imbriquées. Chaque ligne est assemblée dans une instance <code>T</code> et renvoyée une par une via <code>IEnumerable&lt;T&gt;</code> ou <code>IAsyncEnumerable&lt;T&gt;</code>.</p><h2>L'architecture en couches</h2><p>La fonctionnalité LINQ to ES|QL est répartie sur trois packages :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt662bd0dd8861b6b6/6a1705b7a929cf7086ae08a2/41b8aae860ecdc2480edcb1c1d4cc9b03cfb78c9-1999x1036.png" alt="Architecture du package." /><p><em>Architecture des packages.</em>
<a href="https://www.nuget.org/packages/Elastic.Esql"><strong><code>Elastic.Esql</code></strong></a> est le moteur de traduction pur. Il ne dépend d'aucun HTTP et intègre les visiteurs d'expressions, le modèle de requêtes, le formateur et le lecteur de réponses. Vous pouvez l'utiliser de manière autonome pour créer et analyser des requêtes ES|QL sans connexion à Elasticsearch, ce qui est utile pour les tests, la journalisation des requêtes ou la création de votre propre couche d'exécution.</p>// Translation-only: no Elasticsearch connection needed
var provider = new EsqlQueryProvider();
var query = new EsqlQueryable&lt;Product&gt;(provider)
    .From("products")
    .Where(p =&gt; p.InStock)
    .OrderByDescending(p =&gt; p.Price);

Console.WriteLine(query.ToEsqlString());
// FROM products | WHERE in_stock == true | SORT price_usd DESC<p><a href="https://www.nuget.org/packages/Elastic.Clients.Esql"><strong><code>Elastic.Clients.Esql</code></strong></a> est un client ES|QL léger et autonome. Il ajoute l'exécution HTTP en plus de <code>Elastic.Esql</code> via <code>Elastic.Transport</code>. Si votre application n'a besoin que d'ES|QL et d'aucune autre API Elasticsearch, il s'agit de l'option de dépendance minimale.</p><p><a href="https://www.nuget.org/packages/Elastic.Clients.Elasticsearch"><strong><code>Elastic.Clients.Elasticsearch</code></strong></a> est le client complet Elasticsearch .NET. Il s'appuie également sur <code>Elastic.Esql</code> et expose le fournisseur LINQ via l'espace de noms <code>client.Esql</code>. C'est le point d'entrée recommandé pour la plupart des applications.</p><p>Les deux packages de la couche d'exécution fournissent leur propre implémentation de <code>IEsqlQueryExecutor</code>, l'interface de stratégie qui fait le lien entre la traduction et le transport.</p><p>Les trois packages sont compatibles avec Native AOT lorsqu'ils sont utilisés avec un <code>JsonSerializerContext</code> généré par la source. Pour le client complet, consultez la <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/source-serialization#native-aot">documentation Native AOT</a>.</p><h2>Au-delà des bases</h2><p>L'exemple ci-dessus traitait du filtrage, du tri et de la pagination. Le fournisseur prend en charge un ensemble d'opérations plus étendu.</p><h3>Agrégations</h3><p><code>GroupBy</code>, associé aux fonctions d'agrégation dans <code>Select</code>, se traduit en ES|QL <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/stats-by"><code>STATS ... BY</code></a>par :</p>var stats = client.Esql.Query&lt;Product, object&gt;(q =&gt; q
    .GroupBy(p =&gt; p.Brand)
    .Select(g =&gt; new
    {
        Brand = g.Key,
        Count = g.Count(),
        AvgPrice = g.Average(p =&gt; p.Price),
        MaxPrice = g.Max(p =&gt; p.Price)
    }));

// -&gt; FROM products | STATS COUNT(*), AVG(price_usd), MAX(price_usd) BY brand<h3>Projections</h3><p><code>Select</code>, avec des types anonymes, génère les commandes <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/eval"><code>EVAL</code></a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/keep"><code>KEEP</code></a> et <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/rename"><code>RENAME</code></a> :</p>var query = client.Esql.CreateQuery&lt;Product&gt;()
    .Select(p =&gt; new { ProductName = p.Name, p.Price, p.InStock });

// -&gt; FROM products | KEEP name, price_usd, in_stock | RENAME name AS ProductName<h3>Bibliothèque riche en fonctions</h3><p>Plus de 80 fonctions ES|QL sont disponibles via la classe <code>EsqlFunctions</code>, couvrant la gestion des dates et heures, des chaînes de caractères, des opérations mathématiques, des adresses IP, la correspondance de modèles et le calcul de scores. Les méthodes standard <code>Math.*</code> et <code>string.*</code> se traduisent également par :</p>.Where(p =&gt; p.Name.Contains("Pro"))       // -&gt; WHERE name LIKE "*Pro*"
.Where(p =&gt; EsqlFunctions.CidrMatch(      // -&gt; WHERE CIDR_MATCH(ip, "10.0.0.0/8")
    p.IpAddress, "10.0.0.0/8"))<h3>LOOKUP JOIN</h3><p>Les recherches par index croisé se traduisent en ES|QL <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/lookup-join"><code>LOOKUP JOIN</code></a>par :</p>var enriched = client.Esql.Query&lt;Product, object&gt;(q =&gt; q
    .LookupJoin&lt;Product, CategoryLookup, string, object&gt;(
        "category-lookup-index",
        product =&gt; product.Id,
        category =&gt; category.CategoryId,
        (product, category) =&gt; new { product.Name, category!.CategoryLabel }));<h3>Séquence d'échappement pour ES|QL brut</h3><p>Pour les fonctionnalités ES|QL non encore prises en charge par le fournisseur LINQ, vous pouvez ajouter des fragments bruts :</p>var results = client.Esql.Query&lt;Product&gt;(q =&gt; q
    .Where(p =&gt; p.InStock)
    .RawEsql("| EVAL discounted = price_usd * 0.9"));<h3>Requêtes asynchrones côté serveur</h3><p>Pour les requêtes de longue durée, soumettez-les pour un traitement en arrière-plan sur le serveur :</p>await using var asyncQuery = await client.Esql.SubmitAsyncQueryAsync&lt;Product&gt;(
    q =&gt; q.Where(p =&gt; p.InStock),
    asyncQueryOptions: new EsqlAsyncQueryOptions
    {
        WaitForCompletionTimeout = TimeSpan.FromSeconds(5),
        KeepAlive = TimeSpan.FromMinutes(10)
    });

await asyncQuery.WaitForCompletionAsync();
await foreach (var product in asyncQuery.AsAsyncEnumerable())
    Console.WriteLine(product.Name);<p>Les requêtes asynchrones côté serveur sont particulièrement utiles pour les requêtes analytiques de longue durée/le traitement de grands ensembles de données, qui peuvent dépasser les seuils de délai d'expiration habituels, ou dans les environnements sensibles aux délais d'expiration avec équilibreurs de charge, passerelles API ou proxys qui imposent des délais d'expiration HTTP stricts. Les requêtes asynchrones évitent les interruptions de connexion en découplant la soumission et la récupération des résultats.</p><h2>Premiers pas</h2><p>LINQ to ES|QL est disponible à partir de :</p><ul><li><p><strong>Elastic.Clients.Elasticsearch v9.3.4</strong> (branche 9.x)</p></li><li><p><strong>Elastic.Clients.Elasticsearch v8.19.18</strong> (branche 8.x)</p></li></ul><p>Installation depuis NuGet :</p><p><code>dotnet add package Elastic.Clients.Elasticsearch</code></p><p>Les points d’entrée sont sur <code>client.Esql</code>:</p><p>Méthode</p><p>Retours</p><p>Cas d'utilisation</p><p>Query&lt;T&gt;(...)</p><p>IEnumerable&lt;T&gt;</p><p>Exécution synchrone</p><p>QueryAsync&lt;T&gt;(...)</p><p>IAsyncEnumerable&lt;T&gt;</p><p>Streaming asynchrone</p><p>CreateQuery&lt;T&gt;()</p><p>IEsqlQueryable&lt;T&gt;</p><p>Composition et inspection avancées</p><p>SubmitAsyncQueryAsync&lt;T&gt;(...)</p><p>EsqlAsyncQuery&lt;T&gt;</p><p>Requêtes de longue durée côté serveur</p><p>Pour une description complète des fonctionnalités, notamment les options de requête, l'accès à plusieurs champs, les objets imbriqués et la gestion des champs à valeurs multiples, consultez la <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/linq-to-esql">documentation LINQ to ES|QL</a>.</p><h2>Conclusion</h2><p>LINQ to ES|QL apporte toute la puissance d'expression de LINQ to C# au langage de requêtes ES|QL d'Elasticsearch, vous permettant d'écrire des requêtes fortement typées et composables sans avoir à les concevoir manuellement. Grâce à la capture automatique des paramètres, la matérialisation en flux continu et une architecture de packages modulaire scalable, allant d'une simple traduction à un client Elasticsearch complet, il s'intègre naturellement aux applications .NET de toute taille. applications .NET de toute taille. Installez le client le plus récent, configurez vos expressions LINQ pour qu'elles pointent vers un index, et laissez le fournisseur gérer le reste.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/linq-esql-c-elasticsearch-net-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/linq-esql-c-elasticsearch-net-client</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[Base vectorielle]]></category>
    <dc:creator><![CDATA[Florian Bernd,Martijn Laarman]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdfa35fbcbbf4959f/6a1705b9dc55de19a4e00d07/e54132e915217063e9ed0ec45059c6cfc38e31dd-1280x720.png" length="0" type="image/png"/>
    <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Statistiques ES|QL plus rapides avec des tables de hachage de style suisse]]></title>
    <description><![CDATA[Comment le hachage d'inspiration suisse et la conception compatible SIMD permettent d'obtenir des accélérations constantes et mesurables dans le langage de requête Elasticsearch Query Language (ES|QL).]]></description>
    <content:encoded><![CDATA[<p>Nous avons récemment remplacé des éléments clés de l'implémentation des tables de hachage d'Elasticsearch par une conception de type suisse et constaté des temps de construction et d'itération jusqu'à 2 à 3 fois plus rapides sur des charges de travail uniformes à forte cardinalité. Il en résulte une latence réduite, un meilleur débit et des performances plus prévisibles pour les opérations statistiques et analytiques du langage de requête Elasticsearch (ES|QL).</p><h2>Pourquoi c'est important</h2><p>La plupart des workflows analytiques classiques se résument finalement à regrouper des données. Qu'il s'agisse de calculer la consommation moyenne de données par hôte, de compter les événements par utilisateur ou d'agréger des indicateurs selon différentes dimensions, l'opération de base reste la même : associer des clés à des groupes et mettre à jour les agrégats en cours.</p><p>À petite échelle, presque n'importe quelle table de hachage convenable fonctionne bien. À grande échelle (des centaines de millions de documents et des millions de groupes distincts), les détails commencent à avoir leur importance. Les facteurs de charge, la stratégie de sondage, l'organisation de la mémoire et le comportement du cache peuvent faire la différence entre des performances linéaires et une avalanche d'erreurs de cache.</p><p>Elasticsearch prend en charge ces charges de travail depuis des années, mais nous cherchons constamment à moderniser ses algorithmes de base. C'est pourquoi nous avons évalué une nouvelle approche inspirée des tables suisses et l'avons appliquée au calcul des statistiques par ES|QL.</p><h2>Que sont exactement les tables suisses ?</h2><p>Les tables suisses sont une famille de tables de hachage modernes popularisées par SwissTable de Google, puis adoptées par Abseil et d'autres bibliothèques.</p><p>Les tables de hachage traditionnelles passent beaucoup de temps à rechercher des pointeurs ou à charger des clés pour finalement constater qu'elles ne correspondent pas. La caractéristique principale des tables suisses est leur capacité à rejeter la plupart des requêtes grâce à une structure de tableau en cache de petite taille, stockée séparément des clés et des valeurs et appelée <em>octets de contrôle</em>, ce qui réduit considérablement le trafic mémoire.</p><p>Chaque octet de contrôle représente un emplacement unique et, dans notre cas, encode deux éléments : si l'emplacement est vide et une courte empreinte numérique dérivée du hachage. Ces octets de contrôle sont disposés de manière contiguë en mémoire, généralement par groupes de 16, idéal pour le traitement SIMD (<a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">Single Instruction, Multiple Data</a>).</p><p>Au lieu de sonder un emplacement à la fois, les tables suisses parcourent un bloc entier d'octets de contrôle à l'aide d'instructions vectorielles. En une seule opération, le processeur compare l'empreinte de la clé entrante à 16 emplacements et élimine les entrées vides. Seuls les candidats retenus après ce parcours rapide nécessitent le chargement et la comparaison des clés réelles.</p><p>Cette conception privilégie une meilleure localité du cache et réduit considérablement les chargements aléatoires, au détriment d'une petite quantité de métadonnées supplémentaires. À mesure que la table s'agrandit et que les chaînes de détection s'allongent, ces avantages deviennent de plus en plus précieux.</p><h2>SIMD au centre</h2><p>La vraie star de la série est l'architecture SIMD.</p><p>Les octets de contrôle sont non seulement compacts, mais aussi conçus spécifiquement pour être traités par des instructions vectorielles. Une seule comparaison SIMD peut vérifier simultanément 16 empreintes, transformant ainsi une boucle classique en quelques opérations étendues. Exemple :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1f710e87dd749ab3/6a170cc46234e052dadb1a49/bd418778f0c6144f8f5f18419f6220ac0c935c7a-903x407.png" alt="Le SIMD au centre d'Elasticsearch" /><p>En pratique, cela signifie :</p><ul><li><p>Moins de branches.</p></li><li><p>Des chaînes de détection plus courtes.</p></li><li><p>Moins de chargements depuis la mémoire des clés et des valeurs.</p></li><li><p>Une bien meilleure utilisation des unités d'exécution du processeur.</p></li></ul><p>La plupart des recherches ne dépassent jamais l'étape de l'analyse de l'octet de contrôle. Lorsqu'elles y parviennent, le travail restant est ciblé et prévisible. C'est précisément le type de charge de travail pour lequel les processeurs modernes excellent.</p><h2>SIMD sous le capot</h2><p>Pour les lecteurs qui aiment jeter un œil sous le capot, voici ce qui se passe lors de l'insertion d'une nouvelle clé dans la table. Nous utilisons l'API Panama Vector avec des vecteurs de 128 bits, opérant ainsi sur 16 octets de contrôle en parallèle.</p><p>L'extrait suivant montre le code généré sur un processeur Intel Rocket Lake avec AVX-512. Bien que les instructions reflètent cet environnement, la conception ne dépend pas d'AVX-512. Les mêmes opérations vectorielles de haut niveau sont émises sur d'autres plateformes en utilisant des instructions équivalentes (par exemple, AVX2, SSE ou NEON).</p>; Load 16 control bytes from the control block
vmovdqu xmm0, XMMWORD PTR [r9+r10*1+0x10]

; Broadcast the 7-bit fingerprint of the new key across the vector
vpbroadcastb xmm1, r11d

; Compare all 16 control bytes to the new fingerprint
vpcmpeqb k7, xmm0, xmm1
kmovq rbx, k7

; Check if any matches were found
test rbx, rbx
jne &lt;handle_match&gt;<p>Chaque instruction a un rôle clair dans le processus d'insertion :</p><ul><li><p><code>vmovdqu</code>: Charge 16 octets de contrôle consécutifs dans le registre <code>xmm0</code> de 128 bits.</p></li><li><p><code>vpbroadcastb</code>: Réplique l'empreinte 7 bits de la nouvelle clé sur toutes les voies du registre <code>xmm1</code>.</p></li><li><p><code>vpcmpeqb</code>: Compare chaque octet de contrôle à l'empreinte diffusée, produisant un masque de correspondances potentielles.</p></li><li><p><code>kmovq</code> + <code>test</code> : Déplace le masque vers un registre à usage général et vérifie rapidement si une correspondance existe.</p></li></ul><p>Enfin, nous avons opté pour le sondage de groupes de 16 octets de contrôle à la fois, car les tests comparatifs ont montré que l'extension à 32 ou 64 octets avec des registres plus larges n'apportait aucun avantage mesurable en termes de performances.</p><h2>Intégration dans ES|QL</h2><p>L'adoption du hachage suisse dans Elasticsearch n'a pas été une simple solution de remplacement. ES|QL impose des exigences strictes de gestion de la mémoire, de sécurité et d'intégration au reste du moteur de calcul.</p><p>Nous avons étroitement intégré la nouvelle table de hachage à la gestion de la mémoire d'Elasticsearch, notamment au recycleur de pages et à la comptabilisation des coupures, afin de garantir la visibilité et la limitation des allocations. Les agrégations d'Elasticsearch sont stockées de manière dense et indexées par un identifiant de groupe, ce qui optimise la structure de la mémoire et la rapidité d'itération, tout en autorisant certaines optimisations de performance grâce à l'accès aléatoire.</p><p>Pour les clés binaires de longueur variable, nous mettons en cache le hachage complet ainsi que l'identifiant du groupe. Cela évite le recalcul coûteux des codes de hachage lors du sondage et améliore la localité du cache en regroupant les métadonnées associées. Lors du rehachage, nous pouvons nous appuyer sur le hachage et les octets de contrôle mis en cache sans avoir à examiner les valeurs elles-mêmes, ce qui réduit les coûts de redimensionnement.</p><p>Une simplification importante de notre implémentation est que les entrées ne sont jamais supprimées. Cela élimine le besoin de <em>marqueurs</em> (pour identifier les emplacements précédemment occupés) et permet aux emplacements vides de rester véritablement vides, ce qui améliore encore le comportement de sondage et maintient l'efficacité des analyses d'octets de contrôle.</p><p>Le résultat est une conception qui s'intègre naturellement dans le modèle d'exécution d'Elasticsearch tout en préservant les caractéristiques de performance qui rendent les tables suisses attrayantes.</p><h2>Quelles sont ses performances ?</h2><p>Pour les petites cardinalités, les tables suisses offrent des performances globalement équivalentes à celles de l'implémentation existante. Ce résultat est normal : lorsque les tables sont petites, les effets de cache sont moins importants et il y a peu de détections à optimiser.</p><p>À mesure que la cardinalité augmente, la situation change rapidement.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09b13af2fe162f59/6a170cc66f7f04485c9148b8/24900afc47ab07b0e9933f6117b99d0f4613f794-962x599.png" alt="Statistiques ES|QL avec tables de hachage de type suisse" /><p>La carte thermique ci-dessus montre les facteurs d'amélioration du temps de traitement pour différentes tailles de clés (8, 32, 64 et 128 octets) pour des cardinalités allant de 1 000 à 10 000 000 de groupes. À mesure que la cardinalité augmente, le facteur d'amélioration s'accroît régulièrement, jusqu'à 2 à 3 fois pour les distributions uniformes.</p><p>Cette tendance correspond exactement aux prévisions de conception. Une cardinalité plus élevée entraîne des chaînes de détection plus longues dans les tables de hachage traditionnelles, tandis que le mode de sondage de type suisse continue de résoudre la plupart des recherches dans des blocs d'octets de contrôle compatibles SIMD.</p><h2>Le comportement du cache raconte l'histoire</h2><p>Pour mieux comprendre les gains de vitesse, nous avons exécuté le même JMH <a href="https://github.com/elastic/elasticsearch/pull/139343/files#diff-d0e0cc91a7495bf36b2d44eacce95f5185d01879e5f6c38089ac7a89aad17da7"><code>benchmarks</code></a> sous Linux <code>perf</code> et capturé les statistiques du cache et du TLB.</p><p>Comparée à l'implémentation originale, la version suisse effectue environ 60 % d'accès au cache en moins. Les chargements du cache de dernier niveau sont 4 fois moins nombreux, et les défauts de chargement du cache LLC 6 fois moins. Étant donné que ces défauts se traduisent souvent directement par des accès à la mémoire principale, cette réduction explique à elle seule une grande partie de l'amélioration globale des performances.</p><p>Plus on se rapproche du processeur, moins on observe d'échecs de cache de données L1 et près de 6 fois moins d'échecs de TLB de données, ce qui indique une localité spatiale plus étroite et des schémas d'accès à la mémoire plus prévisibles.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb987a5bd98c0d7eb/6a170cc8a929cf9655ae0a25/6e49b7609fba83e33692cb9834552b6ca7e42a83-998x499.png" alt="Comportement du cache : Statistiques originales vs. ES|QL avec tables de hachage de type suisse" /><p>C'est l'avantage concret des octets de contrôle compatibles SIMD. Au lieu de charger sans cesse des clés et des valeurs depuis des emplacements mémoire dispersés, la plupart des requêtes sont résolues par l'analyse d'une structure compacte résidant dans le cache. Moins de mémoire utilisée signifie moins d'échecs de lecture, et moins d'échecs de lecture signifient des requêtes plus rapides.</p><h2>Conclusion</h2><p>En adoptant une conception de table de hachage de style suisse et en misant fortement sur le sondage compatible SIMD, nous avons obtenu des gains de vitesse de 2 à 3 fois pour les charges de travail statistiques ES|QL à cardinalité élevée, ainsi que des performances plus stables et prévisibles.</p><p>Ce travail met en lumière comment les structures de données modernes optimisées pour le processeur peuvent générer des gains substantiels, même pour des problèmes complexes comme les tables de hachage. Il reste encore beaucoup à explorer, notamment en matière de spécialisation des types primitifs et d'utilisation dans d'autres opérations à forte cardinalité, telles que les jointures. Ces pistes s'inscrivent dans le cadre d'un effort plus vaste et continu de modernisation du fonctionnement interne d'Elasticsearch.</p><p>Si vous êtes intéressé par les détails ou souhaitez suivre le travail, consultez cette <a href="https://github.com/elastic/elasticsearch/pull/139343">pull request</a> et la <a href="https://github.com/elastic/elasticsearch/issues/138799">meta issue</a> qui suit les progrès sur Github.</p><p>Bon hachage !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-swiss-hash-stats</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-swiss-hash-stats</guid>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Matthew Alp,Nik Everett]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf76dd688c5b737e6/6a170cc9839dfa7fc7dcff40/21036e031070f14faccb2b53b22723de2750c391-1280x720.png" length="0" type="image/png"/>
    <pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Présentation de la prise en charge d'Elasticsearch dans Google MCP Toolbox for Databases]]></title>
    <description><![CDATA[Découvrez les caractéristiques de la prise en charge d'Elasticsearch maintenant disponible dans Google MCP Toolbox for Databases et utilisez les outils ES|QL pour intégrer en toute sécurité votre index à n'importe quel client MCP.]]></description>
    <content:encoded><![CDATA[<p>Dans cet article, nous allons expliquer comment utiliser Google MCP Toolbox avec <a href="https://github.com/elastic/elasticsearch">Elasticsearch</a> pour créer un outil simple permettant d'extraire des informations d'un index Elasticsearch.</p><p>Nous avons récemment contribué au projet open source <a href="https://github.com/googleapis/genai-toolbox">Google MCP Toolbox for Databases</a> en ajoutant la prise en charge d'Elasticsearch en tant que base de données.</p><p>Grâce à cette nouvelle fonctionnalité, vous pouvez désormais utiliser Google MCP Toolbox pour vous connecter à Elasticsearch et "dialoguer" directement avec vos données.</p><h2>Elasticsearch</h2><p>Nous avons besoin d'une instance Elasticsearch en cours d'exécution. Vous pouvez activer un essai gratuit sur <a href="https://www.elastic.co/cloud">Elastic Cloud</a> ou l'installer localement via le script <a href="https://github.com/elastic/start-local">start-local</a> :</p>curl -fsSL https://elastic.co/start-local | sh<p>Cela installera Elasticsearch et Kibana sur votre ordinateur et générera une clé API à utiliser pour configurer Google MCP Toolbox.</p><p>La clé API sera affichée comme sortie de la commande précédente et stockée dans un fichier .env dans le dossier elastic-start-local.</p><h2>Installer l'ensemble de données d'exemple</h2><p>Après l'installation, connectez-vous à Kibana en utilisant le nom d'utilisateur <em>elastic</em> et le mot de passe généré par le script "start-local" (stocké dans un fichier .env).</p><p>Vous pouvez installer l'ensemble de données <strong>eCommerce orders </strong>disponible dans Kibana. Il comprend un seul index nommé <strong>kibana_sample_data_ecommerce</strong> contenant des informations sur 4 675 commandes provenant d'un site web. Pour chaque commande, nous disposons des informations suivantes :</p><ul><li><p>Informations client (nom, identifiant, date de naissance, e-mail, etc.)</p></li><li><p>Date de la commande</p></li><li><p>ID de la commande</p></li><li><p>Produits (liste de tous les produits avec prix, quantité, ID, catégorie, réduction, etc.)</p></li><li><p>SKU</p></li><li><p>Prix total (hors taxes, taxes incluses)</p></li><li><p>Quantité totale</p></li><li><p>Informations géographiques (ville, pays, continent, localisation, région)</p></li></ul><p>Pour installer les données d'exemple, ouvrez la page <strong>Intégrations</strong> dans Kibana (recherchez "Integration" dans la barre de recherche supérieure), puis installez l'ensemble de données "Sample Data". Pour plus de détails, consultez la documentation ici : <a href="https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana">https://www.elastic.co/docs/explore-analyze/#gs-get-data-into-kibana</a>.</p><p>Cet article a pour but de montrer combien il est facile de configurer Google MCP Toolbox pour se connecter à Elasticsearch et interagir avec l'index <strong>kibana_sample_data_ecommerce</strong> en utilisant le langage naturel.</p><h2>Google MCP Toolbox</h2><p>Google MCP Toolbox est un serveur MCP open source conçu pour faciliter l'interaction sécurisée et efficace des applications et des agents IA avec les bases de données. Auparavant appelé "GenAI Toolbox for Databases", le projet a été renommé après l'adoption d'une compatibilité totale avec le protocole <a href="https://www.anthropic.com/news/model-context-protocol">MCP</a> (Model Context Protocol). Son objectif est de supprimer les tâches complexes traditionnellement requises lors de la connexion d'agents à des bases de données en gérant en arrière-plan les pools de connexion, l'authentification, l'observabilité et d'autres aspects opérationnels.</p><p>Essentiellement, la boîte à outils permet aux développeurs de définir des outils réutilisables de haut niveau qui encapsulent les interactions avec la base de données. Ces outils peuvent ensuite être invoqués par n'importe quel client compatible MCP, tel qu'un agent IA, sans que le client n'ait à implémenter des requêtes SQL de bas niveau ni à gérer des connexions de base de données. Cette approche réduit considérablement la quantité de code répétitif nécessaire à la création d'agents compatibles avec les bases de données, permettant ainsi d'intégrer des opérations de données avancées en seulement quelques lignes de logique applicative. Une fois qu'un outil est défini, il peut être partagé entre plusieurs agents, frameworks, ou langages (Figure 1).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte90070297ee83546/6a16fa29964cea694b08b972/137cea290bb70ad5da21853f9a6358cef4cf7451-1248x1056.png" alt="" /><p>L'un des principaux avantages de la boîte à outils est le modèle de sécurité intégré. Les flux d'authentification tels que OAuth2 et OIDC sont pris en charge de manière native, ce qui permet aux développeurs d'éviter de manipuler ou de stocker des informations sensibles d'identification de base de données dans les agents. La plateforme fournit également des fonctionnalités d'observabilité via OpenTelemetry, y compris les métriques et le traçage, ce qui est essentiel pour le débogage, la surveillance et les déploiements en production. De manière générale, MCP Toolbox sert d'interface unifiée, sécurisée et extensible pour interagir avec vos données depuis n'importe quel système compatible MCP.</p><h2>Comment installer MCP Toolbox</h2><p>Vous pouvez installer le serveur MCP Toolbox sur Linux en utilisant la commande suivante :</p>export VERSION=0.21.0
curl -L -o toolbox https://storage.googleapis.com/genai-toolbox/v$VERSION/linux/amd64/toolbox
chmod +x toolbox<p>Si vous souhaitez l'installer sur macOS ou Windows, vous pouvez suivre les instructions <a href="https://googleapis.github.io/genai-toolbox/getting-started/introduction/#installing-the-server">détaillées ici</a>.</p><h2>Configurer Toolbox pour Elasticsearch</h2><p>Pour configurer MCP Toolbox pour Elasticsearch, nous devons créer un fichier <strong>tools.yaml</strong> comme suit :</p>sources:
  my-cluster:
    kind: elasticsearch
    addresses:
      - http://localhost:9200
    apikey: &lt;insert-here-api-key&gt;

tools:
  customer-orders:
    kind: elasticsearch-esql
    source: my-cluster
    description: Get the orders made by a customer identified by name.
    query: |
    	FROM kibana_sample_data_ecommerce | WHERE MATCH(customer_full_name, ?name, {"operator": "AND"})
    parameters:
      - name: name
        type: string
        description: The customer name.

toolsets:
  elasticsearch-tools:
    - customer-orders<p>Vous devez remplacer la valeur <strong>&lt;insert-here-api-key&gt;</strong> par une clé API Elasticsearch valide. Si vous exécutez Elasticsearch localement avec la commande "start-local", vous trouverez la clé API dans le fichier .env généré par start-local, sous la variable <strong>ES_LOCAL_API_KEY</strong>. Si vous utilisez Elastic Cloud, vous pouvez générer une clé API en suivant la procédure <a href="https://www.elastic.co/docs/deploy-manage/api-keys/elastic-cloud-api-keys">décrite ici</a>.</p><p>Les outils précédents contiennent la requête ES|QL suivante pour Elasticsearch :</p><p>Si vous ne connaissez pas ES|QL, il s'agit d'un langage de requête développé par Elastic, similaire à SQL, qui peut être utilisé pour effectuer des recherches sur un ou plusieurs indices. Pour en savoir plus sur ES|QL, consultez la documentation officielle <a href="https://www.elastic.co/docs/reference/query-languages/esql">ici</a>.</p><p>La requête ci-dessus recherche toutes les commandes stockées dans l'index <strong>kibana_sample_data_ecommerce</strong> qui contiennent le nom du client spécifié, en utilisant le paramètre <strong>?name</strong> (le point d'interrogation indique un paramètre).</p><p>Le nom du client est défini dans la configuration YAML précédente en utilisant le type chaîne et la description "The customer name" (nom du client).</p><p>Cet outil peut être utilisé pour répondre à des questions sur les commandes d'un client, par exemple : <em>Combien de commandes le client Foo a-t-il passées en octobre 2025 ?</em></p><p>Les descriptions des outils et de leurs paramètres sont essentielles pour extraire les informations pertinentes de la requête en langage naturel de l'utilisateur. Cette extraction est réalisée à l'aide de la capacité d'<strong>appel de fonctions</strong> d'un grand modèle de langage (LLM). En pratique, un LLM peut déterminer quelle fonction (outil) doit être exécutée pour obtenir les informations nécessaires, ainsi que les paramètres appropriés pour cette fonction.</p><p>Pour plus d'informations sur les appels de fonctions, nous vous invitons à lire l'article <a href="https://www.elastic.co/search-labs/blog/function-calling-with-elastic">OpenAI function calling with Elasticsearch</a> (en anglais) par Ashish Tiwari.</p><h2>Exécuter le serveur Toolbox</h2><p>Vous pouvez exécuter le serveur MCP Toolbox à l'aide du fichier "tools.yaml" précédent avec la commande suivante :</p>./toolbox --tools-file tools.yaml --ui<p>Le paramètre<strong> –ui</strong> exécute une application web à l'adresse <a href="http://127.0.0.1:5000/ui">http://127.0.0.1:5000/ui</a> (Figure 2).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0fb3953fae603572/6a16fa2aa6c2b92763e794fb/3caf2339b632bafd5847af1ed8b33b518a25b8a2-1600x314.png" alt="" /><p>Sélectionnez <strong>Tools</strong> (Outils) &gt; <strong>customer-orders</strong> et insérez un nom de client dans le paramètre <strong>name</strong> (par ex. Gwen Sanders), puis cliquez sur le bouton <strong>Run Tool</strong> (Exécuter l'outil). Une réponse JSON devrait s'afficher comme illustré dans la figure 3.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltca02df8c78cb39ff/6a16fa2c961e6909b5c4cd22/b167e0142afb8919d9cedf6d0fa431d33d0e55f8-1600x933.png" alt="" /><p>La configuration est terminée et MCP Toolbox peut exécuter l'outil <strong>customer-orders</strong> pour communiquer avec Elasticsearch, en lançant la requête ES|QL.</p><h2>Utiliser MCP Toolbox avec Gemini CLI</h2><p>Nous pouvons utiliser n'importe quel client MCP pour communiquer avec MCP Toolbox for Databases. Par exemple, nous pouvons choisir <a href="https://github.com/google-gemini/gemini-cli">Gemini CLI</a>, un outil en ligne de commande permettant d'utiliser Gemini. Si vous souhaitez installer Gemini CLI, suivez les instructions <a href="https://geminicli.com/docs/get-started/installation/">indiquées ici</a>.</p><p>Gemini CLI propose une extension préconfigurée pour MCP Toolbox, disponible sur <a href="https://github.com/gemini-cli-extensions/mcp-toolbox">gemini-cli-extensions/mcp-toolbox</a>. Vous pouvez installer cette extension en exécutant la commande suivante :</p>gemini extensions install https://github.com/gemini-cli-extensions/mcp-toolbox<p>Après l'installation, vous devez accéder au répertoire dans lequel vous avez stocké le fichier de configuration "tools.yaml" pour MCP Toolbox et exécuter Gemini CLI comme suit (cette étape est nécessaire pour que Gemini CLI soit automatiquement configuré avec MCP Toolbox) :</p>gemini<p>Un message de sortie devrait s'afficher comme illustré dans la figure 4.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf7245c10b9e32cd6/6a16fa2d964cea073208b976/0f22df6d3da13c1dc50dcb560414fa7c630eb9a7-1434x341.png" alt="" /><p>Vous pouvez vérifier si la boîte à outils MCP est connectée en utilisant la commande suivante :</p>/mcp list<p>Vous devriez voir s'afficher <strong>mcp_toolbox</strong> avec les outils<strong> customer-orders</strong> répertoriés (Figure 5).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte857b42dbe604203/6a16fa2f8b73cb531b189e33/97edbc40de9e44f469f6f3a09427532be167de0e-493x155.png" alt="" /><p>Si MCP Toolbox est connecté à Gemini CLI, nous pouvons maintenant poser quelques questions, telles que : "<em>Indiquez-moi les commandes pour la cliente Gwen Sanders</em>". Gemini CLI demande alors l'autorisation d'exécuter l'outil "customer-orders" depuis le serveur mcp_toolbox (voir Figure 6).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfb7ea752c1a39da7/6a16fa30cdacbfdf937d27ff/c052f3b5e49436903b804280c0065f67ee02444b-1432x284.png" alt="" /><p>Après confirmation, Gemini CLI exécute la requête dans MCP Toolbox, reçoit une réponse JSON et l'utilise pour mettre en forme la réponse (Figure 7).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb9f6e04987137a9f/6a16fa320811ae2297e9fef7/7ea5128f1705951c2757af6da4b456d394d4a080-1432x734.png" alt="" /><p>La réponse de Gemini CLI indique que Gwen Sanders a passé une seule commande de 2 produits, pour un prix total de 132 EUR.</p><h2>SDK MCP Toolbox</h2><p>Google MCP Toolbox propose également un SDK pour accéder à toutes les fonctionnalités depuis un programme écrit en Go, Python et Javascript.</p><p>Par exemple, le SDK Python est disponible sur Github à la page suivante : <a href="https://github.com/googleapis/mcp-toolbox-sdk-python">https://github.com/googleapis/mcp-toolbox-sdk-python</a>.</p><p>Nous devons créer un agent simple pour nous connecter à MCP Toolbox. Nous devons installer les packages suivants :</p>pip install toolbox-core
pip install google-adk<p>Et créer un nouveau projet d'agent à l'aide la commande suivante :</p>adk create my_agent<p>Cela créera un nouveau répertoire nommé <strong>my_agent</strong> contenant un fichier <strong>agent.py</strong>.</p><p>Mettez à jour le fichier <strong>my_agent/agent.py</strong> avec le contenu suivant pour vous connecter à Toolbox :</p>from google.adk import Agent
from google.adk.apps import App
from toolbox_core import ToolboxSyncClient

client = ToolboxSyncClient("http://127.0.0.1:5000")

root_agent = Agent(
    name='root_agent',
    model='gemini-2.5-flash',
    instruction="You are a helpful AI assistant designed to search information about a dataset of ecommerce orders.",
    tools=client.load_toolset(),
)

app = App(root_agent=root_agent, name="my_agent")<p>Créez un fichier <strong>.env</strong> avec votre clé API Google :</p>echo 'GOOGLE_API_KEY="YOUR_API_KEY"' &gt; my_agent/.env<p>Enfin, nous pouvons lancer l'exécution de l'agent et observer les résultats. Pour ce faire, exécutez la commande suivante :</p>adk run my_agent<p>Ou, vous pouvez le servir via une interface web :</p>adk web --port 8000<p>Dans les deux cas, vous pouvez interagir avec MCP Toolbox à l'aide d'une interface de questions-réponses. Par exemple, vous pouvez poser la question précédente : <em>Indiquez-moi les commandes de la cliente Gwen Sanders</em>.</p><p>Pour plus d'informations sur les différents SDK, consultez cette <a href="https://googleapis.github.io/genai-toolbox/sdks/">page de documentation</a>.</p><h2>Conclusion</h2><p>Dans cet article, nous avons démontré l'intégration d'Elasticsearch pour Google MCP Toolbox for Databases. À l'aide d'un simple fichier de configuration YAML, nous pouvons définir un ensemble d'outils qui traduisent les questions en langage naturel en requêtes Elasticsearch en utilisant le langage ES|QL.</p><p>Nous avons montré comment interagir avec l'ensemble de données "kibana_sample_data_ecommerce", qui contient des commandes provenant d'un site web. Avec ce fichier de configuration, nous pouvons simplement lancer l'exécution du serveur MCP Toolbox et nous y connecter depuis n'importe quel client MCP.</p><p>Enfin, nous avons démontré comment utiliser Gemini CLI en tant que client pour nous connecter à MCP Toolbox for Databases et interroger les données e-commerce stockées dans Elasticsearch. Nous avons exécuté une requête en langage naturel pour récupérer des informations sur les commandes d'un client spécifique identifié par son nom.</p><p>À mesure que l'écosystème MCP se développe, ce modèle – des définitions d'outils légères soutenues par une infrastructure sécurisée et prête pour la production – crée de nouvelles possibilités pour construire des agents de plus en plus performants et sensibles aux données avec un minimum d'efforts. Qu'il s'agisse d'expérimenter localement les ensembles de données Elastic ou d'intégrer des fonctionnalités de recherche dans une application plus vaste, MCP Toolbox fournit une base fiable et extensible pour interagir avec vos données Elasticsearch en langage naturel.</p><p>Pour en savoir plus sur le développement d'applications d'IA agentique, consultez l'article <a href="https://search-labs-redesign.vercel.app/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">Construire des workflows d'IA agentique avec Elasticsearch</a> par Anish Mathur et Dana Juratoni.</p><p>Pour plus d'informations sur Google MCP Toolbox, consultez la page <a href="https://googleapis.github.io/genai-toolbox/getting-started/introduction/">vhttps://googleapis.github.io/genai-toolbox/getting-started/introduction/</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/google-mcp-toolbox-elasticsearch-support</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/google-mcp-toolbox-elasticsearch-support</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[IA agentique]]></category>
    <dc:creator><![CDATA[Enrico Zimuel,Laurent Saint-Félix]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt72d49893c51407cf/6a16fa33cf4f2502bab2cf7e/425a48691f436ed47c9bdfaf5d561ac122b2c472-1062x668.png" length="0" type="image/png"/>
    <pubDate>Fri, 12 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[ES|QL dans la version 9.2 : jointures Smart Lookup et prise en charge des séries temporelles]]></title>
    <description><![CDATA[Découvrez trois nouveautés d’ES|QL dans Elasticsearch 9.2 : une jointure LOOKUP optimisée pour une corrélation de données plus expressive, la nouvelle commande TS pour l’analyse des séries temporelles, et la commande flexible INLINE STATS pour l’agrégation.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch 9.2, sorti en octobre, est doté d'avancées significatives qui rendent l'analyse de vos données plus rapide, plus flexible et plus accessible que jamais. Au cœur de cette version se trouvent d'importantes améliorations apportées à ES|QL, notre langage de requêtes canalisées, conçu pour apporter encore plus de valeur directement aux utilisateurs finaux.</p><p>Découvrez les fonctionnalités d’Elasticsearch 9.2 qui révolutionneront votre analyse de données avec ES|QL.</p><h2>Révolutionner la corrélation des données : un Lookup Join plus intelligent, plus rapide et plus flexible</h2><p>La commande <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/lookup-join">LOOKUP JOIN</a> dans ES|QL a subi une transformation importante dans Elasticsearch 9.2, elle devient considérablement plus efficace et polyvalente. LOOKUP JOIN fusionne les données issues de la table de résultats de votre requête ES|QL avec les enregistrements concordants d’un index de mode de recherche que vous avez désigné. Cela permet d’ajouter des champs de l’index de recherche en tant que nouvelles colonnes à votre table de résultats, en faisant correspondre les valeurs du champ de jointure. Auparavant, la jointure des données était limitée à un seul champ et à une simple égalité. Plus maintenant ! Ces améliorations vous permettent de gérer facilement des scénarios complexes de corrélation de données.</p><p><strong>Les principales améliorations de Lookup Join incluent :</strong></p><ul><li><p><strong>Jointures multi-champs :</strong> Effectuez facilement des jointures sur plusieurs champs. Par exemple, pour joindre <code>application_logs</code> à <code>service_registry</code> sur <code>service_name</code>, <code>environment</code> et <code>version:</code></p></li></ul>FROM application_logs
| LOOKUP JOIN service_registry ON service_name, environment, version<ul><li><p><strong>Utilisation d’expressions pour des prédicats de jointure complexes (aperçu technologique) :</strong></p></li></ul><p>Vous n'êtes plus limité à la simple égalité. LOOKUP JOIN permet désormais de spécifier <strong>plusieurs critères</strong> de corrélation et d’incorporer une gamme <strong>d’opérateurs binaires,</strong> notamment ==, !=, &lt;, &gt;, &lt;=et &gt;=. Cela signifie que vous pouvez créer des conditions de jointure très nuancées, vous permettant de poser des questions beaucoup plus sophistiquées à vos données.</p><p>Exemple 1 : Recherche des métriques d’application avec un seuil de SLA par service</p>FROM application_metrics
| LOOKUP JOIN sla_thresholds
      ON service_name == sla_service AND response_time &gt; sla_response_time<p>Exemple 2 : Cette requête calcule le montant dû, en se basant sur les politiques tarifaires régionales qui évoluent au fil du temps. Cela relie trois ensembles de données basés sur des périodes complexes et des conditions d’égalité pour calculer un <code>due_amount</code>final. La deuxième jonction de recherche utilise le champ <code>measurement_date</code> de l’indice <code>meter_readings</code> et le champ <code>region_id</code> de l’indice <code>customers</code> pour joindre l’indice <code>pricing_policies</code> et trouver la politique de tarification appropriée pour le <code>region</code> et le <code>measurement_date</code> particuliers.</p>FROM meter_readings
| LOOKUP JOIN customers
      ON meter_id
| LOOKUP JOIN pricing_policies
      ON
        region_id == region AND
          measurement_date &gt;= policy_begin_date AND
          measurement_date &lt; policy_end_date
| EVAL due_amount = (kwh_consumed * rate_per_kwh + base_charge) * (1 + tax_rate)
| EVAL period = policy_name
| KEEP customer_name, period, due_amount, measurement_date, kwh_consumed,
    rate_per_kwh, base_charge, tax_rate
| SORT measurement_date<ul><li><p><strong>Des gains de performances considérables pour les jointures filtrées : </strong></p></li></ul><p>Nous avons amélioré les performances des « jointures en expansion » qui sont filtrées à l'aide de conditions de table de recherche. Les jointures en expansion produisent plusieurs correspondances par ligne d'entrée, ce qui peut créer de grands ensembles de résultats intermédiaires. Cela s’aggrave lorsqu’un filtre ultérieur écarte un grand nombre de ces lignes. Avec la version 9.2, nous optimisons ces jointures en excluant les lignes superflues lorsqu’un filtre est appliqué aux données de recherche, ce qui permet d’éviter de traiter des lignes vouées à être éliminées. Dans certains scénarios, ces jointures peuvent être jusqu'à <strong>1000 fois plus rapides</strong> !</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltce2c948a9a00a348/6a17f1a20b0bed8c08dd368b/002c014ee29b1aaf9ddeb8c554bb76efe3ed180c-1572x954.png" alt="Gains de performance des jointures filtrées" /><p>Cette optimisation est déterminante pour gérer les « jointures à résultats multiples », là où une consultation initiale peut produire de nombreux résultats potentiels. La transmission intelligente des filtres garantit que seules les données pertinentes sont traitées, réduisant ainsi fortement le temps d’exécution des requêtes pour une analyse en temps réel sur des ensembles de données gigantesques. Cela signifie que vous obtenez vos informations beaucoup plus rapidement, même avec des opérations de jointure très volumineuses ou complexes.</p><p><strong>Recherchez la compatibilité de Lookup Join avec la rechercher inter-clusters (CCS) :</strong></p><p>Lorsque Lookup Join est devenu disponible en version générale dans les versions 8.19 et 9.1, il manquait le support de la recherche inter-clusters (CCS). LOOKUP JOIN s’intègre parfaitement à CCS en 9.2, ce qui est un atout majeur pour les entreprises gérant plusieurs clusters. Placez simplement votre index de recherche sur tous les clusters distants où vous souhaitez effectuer une jointure, et ES|QL utilisera automatiquement ces index de recherche distants pour la jointure avec vos données distantes. Cela simplifie l'analyse distribuée des données et garantit un enrichissement constant sur l'ensemble de votre déploiement Elasticsearch.</p><p>Ces améliorations vous permettent de corréler divers ensembles de données avec une précision, une rapidité et une facilité sans précédent, afin de découvrir des informations plus approfondies et plus exploitables sans solutions complexes ni étapes de prétraitement.</p><h2>Enrichissez vos données en toute simplicité : Kibana Discover UX pour les index de recherche</h2><p>L’enrichissement des données doit rester simple, et non constituer un problème. Une fantastique nouvelle expérience utilisateur a été ajoutée à Discover (Kibana) pour créer et gérer les index de recherche.</p><p><strong>Workflow intuitif : la fonction de</strong> saisie semi-automatique complète de Discover vous guidera tout au long du processus, en suggérant des index de recherche et des champs de jointure dans l’éditeur ES|QL, ce qui facilite grandement la connexion de vos données téléchargées avec les index existants. Tapez le nom d'un index de recherche qui n'existe pas et accédez directement à l'éditeur de recherche en un seul clic pour créer l'index. Tapez le nom d'un index de recherche existant, et nous vous suggérerons une option pour le modifier :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt20a75bcfd25eb156/6a17f1a46864a4864db688a1/d36fd6ffd6bc0bf8d31067f6266445c68d15c71c-1400x184.png" alt="" /><p><strong>Gestion en ligne (CRUD) :</strong> maintenez vos ensembles de données de référence à jour grâce à des fonctionnalités d'édition en ligne (création, lecture, mise à jour, suppression) directement dans Discover.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6263c5dd8c2c9d7e/6a17f1a5af47b614dbcde095/a0e4aa66540b1f725c24ccb0519d978415073bb6-1453x842.png" alt="Exemple d'une requête LOOKUP" /><p><strong>Téléchargement de fichiers sans effort : </strong>vous pouvez désormais télécharger directement des fichiers, tels que des CSV, dans Discover et les utiliser instantanément dans vos <code>LOOKUP JOIN</code>. Plus besoin de changer constamment de contexte en naviguant entre les différentes zones de Kibana !</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltddfcc3580af0e5c6/6a17f1a73e9e45965aba1587/0f5dc2c712af4c4cada50292a7c8b836eb02aa67-1600x748.png" alt="Ajoutez facilement des données à un index de recherche et utilisez-les dans LOOKUP JOIN" /><p>Cette fonctionnalité démocratise l’enrichissement des données, que vous mappiez des ID utilisateur à des noms, ajoutiez des métadonnées d’entreprise ou joigniez des fichiers de référence statiques. La puissance des jointures est désormais à la portée de tous, de manière rapide, simple et au même endroit.</p><h2>Préservez votre contexte : présentation d'INLINE STATS (aperçu technique)</h2><p>L'agrégation des données est cruciale, mais parfois vous avez besoin de voir les agrégations <em>à côté de</em> vos données originales. Nous sommes ravis de présenter les <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/inlinestats-by">STATS EN LIGNE</a> en tant que fonctionnalité de la <strong>Tech Preview.</strong></p><p>Contrairement à la commande <code>STATS</code>, qui remplace vos champs d'entrée par une sortie agrégée, <code>INLINE STATS</code> préserve tous vos champs d'entrée d'origine et ajoute simplement les nouveaux champs agrégés. Cela vous permet d’effectuer des opérations supplémentaires sur vos champs d’entrée originaux <em>après</em> l’agrégation, offrant ainsi un workflow d’analyse plus continu et plus flexible.</p><p>Par exemple, pour calculer la distance moyenne des vols tout en conservant les lignes de vol individuelles :</p>FROM kibana_sample_data_flights
 | KEEP Carrier, Dest, DistanceMiles
 | INLINE STATS avgDist = ROUND(AVG(DistanceMiles))
       BY Dest
 | WHERE DistanceMiles &gt; avgDist<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9e0c7209db8a67ad/6a17f1a9e8fbcee5233a1a53/6eea943035e0ab371270084c504a06bb89f8b82b-1496x290.png" alt="Filtrer les résultats de vol avec une distance supérieure à la moyenne en utilisant l’avgDist " /><p>Dans cette requête, <code>avgDist</code> est ajouté à chaque ligne avec le <code>Dest</code>correspondant (ination) par lequel nous avons regroupé, puis, comme nous avons toujours les colonnes d’information de vol, nous pouvons filtrer les résultats vers les vols ayant une distance supérieure à la moyenne.</p><h2>Prise en charge des séries temporelles dans ES|QL (aperçu technique)</h2><p>Elasticsearch utilise des <a href="https://www.elastic.co/docs/manage-data/data-store/data-streams/time-series-data-stream-tsds">flux de données temporelles</a> pour stocker des métriques. Nous ajoutons la prise en charge des agrégations de séries temporelles dans ES|QL, via la commande source <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/ts"><code>TS</code></a> . Cette fonctionnalité est disponible dans Elastic Cloud serverless et en version 9.2 (niveau Basic) en préversion technique.</p><p>L’analyse de séries temporelles est principalement basée sur des requêtes d’agrégation qui résument les valeurs de métriques sur des plages de temps, segmentées par une ou plusieurs dimensions de filtrage. La majorité des requêtes d’agrégation nécessitent un traitement en deux étapes, avec (a) une fonction d’agrégation interne qui résume les valeurs de chaque série temporelle, et (b) une fonction d’agrégation externe qui consolide les résultats de (a) au travers des séries temporelles.</p><p>La commande source <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/ts"><code>TS</code></a>, combinée à <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/stats-by"><code>STATS</code></a>, offre un moyen concis et efficace d'exprimer de telles requêtes sur des séries temporelles. Plus concrètement, considérons l’exemple suivant pour calculer le taux total de requêtes par hôte et par heure :</p>TS my_metrics
| WHERE @timestamp &gt; NOW() - 1 day
| STATS SUM(RATE(requests))
      BY host, TBUCKET(1h)<p>Dans ce cas, la fonction d'agrégation de séries chronologiques <code>RATE</code> est d'abord évaluée par série chronologique et par heure. Les agrégats partiels produits sont ensuite combinés à l'aide de <code>SUM</code> pour calculer les valeurs agrégées finales par hôte et par heure.</p><p>Vous pouvez consulter la liste des fonctions d'agrégation de séries temporelles disponibles <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/time-series-aggregation-functions">ici</a>. La fonction <a href="https://www.elastic.co/docs/manage-data/data-store/data-streams/time-series-data-stream-tsds#time-series-metric">counter_rate</a> est désormais prise en charge, sans doute la fonction d’agrégation la plus importante pour le traitement des compteurs.</p><p>La commande source <code>TS</code> est conçue pour être combinée avec <code>STATS</code>, avec une exécution adaptée pour prendre en charge efficacement les agrégations de séries temporelles. Par exemple, les données sont triées avant d’entrer dans le <code>STATS</code>. Les commandes de traitement susceptibles d’enrichir ou de modifier les données temporelles ou leur ordre, telles que <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/fork"><code>FORK</code></a> ou <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/inlinestats-by"><code>INLINE STATS</code></a>, ne sont actuellement pas autorisées entre <code>TS</code> et <code>STATS</code>. Cette restriction pourrait être levée à l’avenir.</p><p>La sortie tabulaire de <code>STATS</code> peut être traitée avec n'importe quelle commande applicable. Par exemple, la requête suivante calcule le rapport entre la valeur moyenne de <code>cpu_usage</code> hébergé par hôte et par heure et la valeur maximale par hôte :</p>TS my_metrics
| STATS avg_usage = AVG(AVG_OVER_TIME(cpu_usage))
      BY host, time_bucket = TBUCKET(1h)
| INLINE STATS max_avg_usage = MAX(avg_usage)
      BY host
| EVAL ratio = avg_usage / max_avg_usage
| KEEP host, time_bucket, ratio
| SORT host, time_bucket DESC<p>Les données de séries temporelles sont enregistrées sur notre moteur de stockage sous-jacent à colonnes, optimisé par les doc values de Lucene. La commande TS ajoute une exécution vectorisée de requêtes via le moteur de calcul ES|QL. Les performances des requêtes sont souvent améliorées de plus d'un ordre de grandeur, par rapport aux requêtes <a href="https://www.elastic.co/docs/reference/query-languages/querydsl">DSL</a> équivalentes, et sont comparables aux systèmes établis spécifiques aux métriques. Une analyse détaillée de l’architecture et des performances sera bientôt disponible. Ne manquez pas cette publication.</p><h2>Élargir votre boîte à outils : nouvelles fonctions ES|QL</h2><p>Pour améliorer davantage l’utilité et la polyvalence d’ES|QL, nous avons ajouté une suite de nouvelles <a href="https://www.elastic.co/docs/reference/query-languages/esql/esql-functions-operators">fonctions</a>:</p><p><strong>Manipulation de chaînes : </strong><a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/string-functions#esql-contains">CONTAINS</a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/mv-functions#esql-mv_contains">MV_CONTAINS</a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/string-functions#esql-url_encode">URL_ENCODE</a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/string-functions#esql-url_encode_component">URL_ENCODE_COMPONENT</a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/string-functions#esql-url_decode">URL_DECODE</a> pour un traitement plus robuste du texte et des URL.</p><p><strong>Séries temporelles et géospatial :</strong> <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/grouping-functions#esql-tbucket">TBUCKET</a> pour des buckets temporels flexibles, TO_DENSE_VECTOR pour les opérations vectorielles, et un ensemble complet de <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/spatial-functions">fonctions géospatiales</a> comme <code>ST_GEOHASH</code>, <code>ST_GEOTILE</code>, <code>ST_GEOHEX</code>, <code>TO_GEOHASH</code>, <code>TO_GEOTILE</code>, <code>TO_GEOHEX</code> pour une analyse avancée basée sur la localisation.</p><p><strong>Formatage de la date :</strong> <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions#esql-day_name">DAY_NAME</a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions#esql-month_name">MONTH_NAME</a> pour une représentation plus lisible des dates.</p><p>Ces fonctions vous offrent un ensemble d'outils plus riche pour manipuler et analyser vos données directement dans ES|QL.</p><h2>Sous le capot : plus de performance et d'efficacité</h2><p>Au-delà des fonctionnalités mises en avant, Elasticsearch 9.2 inclut de nombreuses optimisations de performances pour ES|QL. Nous avons accéléré <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/where#like-and-rlike">RLIKE (LIST</a>) avec pushdown dans les cas où la fonction remplace plusieurs requêtes RLIKE similaires. Avec <code>RLIKE</code> (LIST), nous pouvons fusionner ces requêtes en un seul automate et appliquer un automate au lieu de plusieurs. Nous avons également accéléré le chargement des champs de mots clés grâce à des tris d'index et des optimisations générales des requêtes. Ces améliorations garantissent que vos requêtes ES|QL s'exécutent plus efficacement que jamais.</p><h2>Lancez-vous dès aujourd'hui !</h2><p>La version 9.2 d’Elasticsearch représente une avancée majeure pour ES|QL, conférant une puissance et une flexibilité inédites à vos workflows d’analyse de données. Nous vous encourageons à explorer ces nouvelles fonctionnalités et à constater la différence qu’elles apportent.</p><p>Pour une liste complète de tous les changements et améliorations dans Elasticsearch 9.2, veuillez consulter les <a href="https://www.elastic.co/guide/en/elasticsearch/reference/9.2/release-notes-9.2.0.html">notes de publication officielles</a>. Bonne recherche !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-elasticsearch-9-2-multi-field-joins-ts-command</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-elasticsearch-9-2-multi-field-joins-ts-command</guid>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Tyler Perkins,Kostas Krikellas,Julian Kiryakov]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd30ea8cac3809cc3/6a17f1aa4b055dd8734322f8/415894e21e7758c907d6e60d4efc94230349beef-2012x1164.png" length="0" type="image/png"/>
    <pubDate>Tue, 02 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[L'expérience de l'éditeur ES|QL d'Elasticsearch par rapport à l'analyseur d'événements PPL d'OpenSearch]]></title>
    <description><![CDATA[Découvrez comment les fonctionnalités avancées d'ES|QL Editor accélèrent votre flux de travail, en contraste direct avec l'approche manuelle de PPL Event Analyzer d'OpenSearch. 
]]></description>
    <content:encoded><![CDATA[<p>Le <a href="https://www.elastic.co/blog/getting-started-elasticsearch-query-language">langage de requête Elasticsearch</a> (ES|QL), généralement disponible depuis la version 8.14, présente un langage et un moteur de requête conçus pour la recherche, l'observabilité et les enquêtes de sécurité. Contrairement au langage de traitement par pipeline (PPL) d'OpenSearch, qui emprunte largement aux langages de traitement par pipeline existants, ES|QL a été conçu dès le départ pour se concentrer sur la finition, la convivialité et l'intégration transparente sur la plateforme Kibana.</p><p>Dans ce blog, nous allons explorer l'expérience du développeur de l'éditeur ES|QL dans Elasticsearch 9.1 en le comparant à PPL dans l'analyseur d'événements (PPL en abrégé) dans OpenSearch 3.2.</p><p>Les différences apparaissent rapidement : l'éditeur ES|QL offre une autocomplétion intelligente, une aide contextuelle, des requêtes recommandées et une prise en charge des requêtes entre clusters qui permettent aux utilisateurs débutants, mais aussi aux utilisateurs experts, d'être plus autonomes. La conception réfléchie de la rédaction ES|QL est également visible dans l'inspection intégrée des requêtes et l'intégration holistique par le biais des flux de travail Kibana, par exemple, avec les requêtes récentes.</p><p>En revanche, PPL n'offre pas de support comparable pour l'autocomplétion, l'orientation contextuelle et les requêtes distribuées, ce qui entraîne une courbe d'apprentissage plus raide et davantage d'essais et d'erreurs.</p><h2>Faciliter l'apprentissage et l'utilisation d'ES|QL</h2><p>Se lancer dans l'utilisation d'un nouveau langage d'interrogation peut souvent sembler insurmontable. L'éditeur ES|QL<strong>, </strong>intégré directement à <strong>Kibana Discover</strong>, est conçu pour faciliter ce processus en prenant en charge non seulement la création et le débogage des requêtes, mais aussi en accélérant la vitesse à laquelle vous vous familiarisez et vous vous sentez à l'aise avec le langage. Comme l'éditeur aide à réduire les frictions dans les tâches quotidiennes, vous pouvez vous concentrer sur la recherche de solutions plutôt que sur la syntaxe et les essais-erreurs. Pour en savoir plus sur ces principes et sur la manière dont nous les avons intégrés dans l'éditeur <a href="https://www.elastic.co/search-labs/blog/improving-esql-editor-experience-in-kibana">, cliquez ici.</a></p><p>Cette expérience d'éditeur n'est pas limitée à Discover ; il s'agit d'un module de code réutilisable que nous travaillons à <strong>intégrer dans d'autres parties de Kibana</strong>, telles que les tableaux de bord, les alertes Kibana et les cartes Kibana.</p><h3>Autocomplétion intelligente : accélérer la création de requêtes</h3><p>L'autocomplétion de l'éditeur ES|QL est complète, offrant des suggestions de fonctions compatibles, d'arguments, de littéraux et même de fonctions imbriquées, une capacité qui fait notablement défaut dans PPL. En fait, il a été reconstruit de fond en comble, comme indiqué <a href="https://www.elastic.co/search-labs/blog/esql-autocomplete-rebuilt">ici.</a></p><p>La validation s'exécute au fur et à mesure que l'utilisateur tape, comme indiqué <a href="https://www.elastic.co/search-labs/blog/improving-esql-editor-experience-in-kibana">ici</a>, et suggère des champs tout en notifiant l'utilisateur en cas d'erreur. Cela réduit la charge mentale des utilisateurs et permet d'éviter les erreurs dès le début du processus de création de la requête.</p><p>Exemple : Des champs et des fonctions compatibles sont proposés dans cette imbrication :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdb186fc80dcc66f5/6a17f311e9ea8737a5a9c720/a4d7b2819c34fab31bced7873257b8932b623fba-1502x473.png" alt="Suggestion d'imbrication des champs et des fonctions compatibles." /><p>Ce que la PPL ne soutient pas :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt250ae79e8f33b598/6a17f3127f6f150d3dc09c74/6f3a89b1255b8a3a762022a2704fdd1c2987e5f9-1013x335.png" alt="Une fonction PPL n'est pas prise en charge." /><p>Même si l'autocomplétion intelligente vous guide à travers les fonctions compatibles, les arguments et les fonctions imbriquées, il se peut que vous souhaitiez mieux comprendre les options disponibles. C'est précisément là que l'aide contextuelle de l'éditeur ES|QL devient inestimable, offrant une assistance immédiate, au sein de l'éditeur, pour clarifier et améliorer le développement de votre requête.</p><h3>Une aide contextuelle au bout des doigts</h3><p>Il suffit d'un clic Ctrl-Espace pour obtenir des informations supplémentaires sur une commande générée par la saisie semi-automatique. Un panneau apparaît immédiatement avec des détails sur la fonction, l'argument ou le champ en question. Cette interaction légère permet aux développeurs de rester dans le flux, en leur fournissant des conseils juste à temps sans les obliger à quitter l'éditeur ou à rechercher de la documentation externe. Cela permet de réduire le temps perdu en recherches syntaxiques et d'éviter les erreurs courantes avant qu'elles ne se produisent.</p><p>Voici ce que cela donne en pratique :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt407e42acc7f53f15/6a17f3134b055d128d43231a/2797f9b5e002dbd83c46475c4ed4dcdc86144a01-1343x522.gif" alt="Une commande générée par l'autocomplétion avec Ctrl-espace pour un contexte supplémentaire." /><p>PPL ne dispose pas de ce niveau d'orientation intégrée, ce qui oblige les utilisateurs à s'appuyer sur des documents externes ou à procéder par tâtonnements. Cette absence n'est pas seulement une caractéristique manquante ; elle met en évidence une disparité plus large dans la philosophie de conception. ES|QL donne la priorité à une expérience réfléchie et contextuelle qui s'adapte aux données et au flux de travail de l'utilisateur. Cette différence s'accentue au fur et à mesure que les requêtes deviennent plus complexes, ce qui fait de l'Éditeur ES|QL un environnement plus efficace et plus fiable, tant pour l'apprentissage que pour la production.</p><h3>Requêtes recommandées qui tiennent compte du contexte des données</h3><p>L'éditeur ES|QL propose des requêtes recommandées qui sont automatiquement adaptées aux données avec lesquelles vous travaillez, telles que les journaux. Au lieu de présenter un éditeur vierge, il fait apparaître les points de départ les plus pertinents pour les cas d'utilisation courants. La sélection d'une requête recommandée génère une requête canonique qui est immédiatement utilisable et peut être affinée si nécessaire. Cette approche accélère le développement des requêtes, en particulier pour les nouveaux utilisateurs qui ne connaissent pas encore toute la syntaxe.</p><p>Voici un exemple où un utilisateur sélectionne la requête "Détecter le point de changement" :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc6c41f9e1e3cb40/6a17f3156864a43791b688d0/3284c9340d41298820fbf8c7702abad946b48248-925x370.gif" alt="Que se passe-t-il lorsqu'un utilisateur sélectionne la requête &quot;Détecter le point de changement&quot;." /><p>Comparez cela à l'expérience PPL :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6511bb51659feaf3/6a17f3166864a427c2b688d4/5c3e59dadc6210aede3366bdd081887bcbae7a54-969x798.png" alt="L'expérience PPL, avec seulement une autocomplétion de base." /><p>En revanche, PPL n'offre qu'une autocomplétion de base, ce qui vous laisse le soin d'élaborer des requêtes sans contexte ni structure. Ce manque d'orientation peut conduire à la frustration et au tâtonnement.
Grâce aux requêtes recommandées de l'éditeur ES|QL qui tiennent compte des données, vous pouvez éviter de partir de zéro ou de mémoriser la syntaxe pour les tâches de routine. L'éditeur réduit la charge cognitive, aide à prévenir les erreurs et vous permet de vous concentrer sur la résolution de problèmes et sur des objectifs plus larges, tels que l'exécution de recherches entre clusters, plutôt que de vous débattre avec la construction d'une requête.</p><h2>Interrogation intuitive de l'ensemble des clusters</h2><p>L'autocomplétion de l'éditeur ES|QL reste supérieure, même lorsque l'on travaille avec plusieurs clusters distants <a href="https://elastic.aiops.work/search-labs/blog/esql-cross-cluster-search">avec CCS</a>. Voici pourquoi :</p><h3>L'éditeur ES|QL offre une autocomplétion transparente, même à travers les clusters</h3><p>L'autocomplétion dans l'éditeur ES|QL prend en charge non seulement les noms des clusters, mais aussi les<strong> index locaux et distants</strong>. Comme indiqué <a href="https://www.elastic.co/search-labs/blog/esql-cross-cluster-search">ici</a>, cela fonctionne grâce à l'architecture d'un nœud coordinateur, qui aide à valider et à générer le plan d'interrogation à envoyer aux nœuds locaux, à exécuter l'interrogation et à agréger les résultats avant de les renvoyer à l'utilisateur. Sans saisir le nom complet du cluster distant, la saisie de " :" lance le processus d'autocomplétion pour l'index distant. Et vous n'êtes pas limité au préfixe.</p><p>Il est ainsi facile de découvrir et d'interroger des ensembles de données distribués sans avoir à mémoriser des conventions de dénomination ou à changer de contexte.</p><p>Voici un exemple où l'utilisateur tape simplement "clu:g" pour localiser un index distant :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4fadd61aa6d2a212/6a17f3186864a4a385b688d8/bae1fbacb2320e4d07f41291ea57c9bcf15bf8a5-1092x523.gif" alt="Exemple où l'utilisateur tape simplement &quot;clu:g&quot; pour localiser un index distant." /><p>En revanche, la PPL ne fournit qu'une complétion de base pour les index locaux, avec des suggestions limitées aux correspondances de préfixes. Les clusters distants doivent être saisis manuellement, ce qui augmente la probabilité d'erreurs et ralentit la création de requêtes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3949402084cf303a/6a17f31a6864a482b1b688dc/e38793c0cc7c6cc7dc0fd4779a3e24ffbb6e0838-1094x263.gif" alt="Exemple de la façon dont PPL ne fournit qu'une complétion de base pour les index locaux, avec des suggestions limitées aux correspondances de préfixes." /><p>PPL ne fournit une complétion que pour les index locaux et les suggestions sont limitées au préfixe :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcaa81c403f354e1f/6a17f31c6864a4e620b688e0/5310f824942f94485cace2558ea72c56a0971e22-862x197.png" alt="Un autre exemple de la façon dont PPL fournit une complétion uniquement pour les index locaux et les suggestions sont limitées au préfixe." /><p>ES|QL va plus loin en <a href="https://www.elastic.co/docs/solutions/search/cross-cluster-search#exclude-problematic-clusters">autorisant les exclusions</a> directement à l'aide d'un signe négatif, ce qui vous permet de contrôler finement les grappes qui participent à votre exploration. Cette fonction est particulièrement utile lorsque vous travaillez avec des environnements hybrides, où vous pouvez vouloir inclure ou omettre des ensembles de données spécifiques lors d'investigations entre clusters.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf0ca78bfbceb60ae/6a17f31d6864a4199bb688e4/f23ca17f58fbf8e6d27419c028274cb91f30a549-937x78.png" alt="Un exemple de codage d'une enquête inter-clusters." /><p>Ces améliorations reflètent l'accent mis par Elasticsearch sur la réduction des frictions dans la recherche cross-cluster. En facilitant la construction et la gestion des requêtes distribuées, ES|QL Editor permet aux analystes et aux développeurs de se concentrer sur les idées plutôt que sur la syntaxe, alors que PPL laisse une plus grande part de ce fardeau à l'utilisateur. De même que l'éditeur ES|QL simplifie la création de requêtes inter-clusters, il fournit également des outils permettant d'inspecter l'exécution de ces requêtes, garantissant ainsi la transparence et le contrôle des performances sur plusieurs clusters.</p><h3>Utilisation de l'outil Inspect pour analyser les détails de la recherche transversale</h3><p>L'outil Inspect, accessible à partir de l'éditeur ES|QL, est conçu pour fournir des métadonnées contenant des informations explicites sur l'exécution de la requête dans tous les clusters. Cette fonctionnalité est activée dans Kibana Discover et est accessible directement dans l'inspecteur de requête, ce qui vous permet d'analyser la progression et les détails de la recherche, ce qui est particulièrement crucial pour la <strong>recherche cross-cluster</strong> <a href="https://www.elastic.co/docs/reference/query-languages/esql/esql-cross-clusters">(CCS).</a> Cette fonctionnalité vous permet de suivre l'évolution de la recherche et de comprendre comment les requêtes se déroulent dans des ensembles de données distribués.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf79eaeedac3600b9/6a17f31fabe0f26f06dfeb4b/5d1c204f70171526fff924c30ea8ad08121a0f8d-919x523.gif" alt="L'outil d'inspection pour analyser les détails de la recherche entre clusters." /><p>Cette visibilité détaillée de l'exécution des requêtes, en particulier pour les recherches distribuées complexes, vous permet de garantir des performances et un dépannage optimaux.</p><p>Au-delà de la compréhension des mécanismes des requêtes individuelles, ES|QL Editor améliore encore le parcours de l'utilisateur en intégrant des fonctionnalités essentielles dans l'ensemble de la plateforme Kibana, favorisant ainsi un flux de travail transparent et ininterrompu.</p><h2>Expérience des requêtes unifiées avec ES|QL et Kibana</h2><p>Le changement de contexte est l'une des sources de friction les plus courantes dans l'analyse pilotée par les requêtes. Vous devez souvent vous rappeler des requêtes que vous avez déjà écrites. Chaque interruption déconcentre et ralentit les investigations. L'éditeur ES|QL y remédie en intégrant l'historique des requêtes dans Kibana.</p><h3>Requêtes récentes</h3><p>La fonction <a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga">Requêtes récentes</a> de l'éditeur ES|QL vous aide à rester dans le flux en rendant les travaux antérieurs instantanément accessibles. Dans l'éditeur ES|QL de Discover, vous pouvez afficher, réexécuter et enregistrer vos 20 dernières requêtes, de sorte que les requêtes complexes ou fréquemment utilisées ne sont qu'à un clic de souris. Ces requêtes enregistrées se retrouvent également dans Kibana et s'intègrent aux tableaux de bord, aux visualisations, aux alertes et aux cartes, de sorte que vous n'avez pas besoin de quitter votre écran actuel ou de retaper des commandes à partir de zéro. Cela permet de réduire le travail répétitif, d'accélérer les enquêtes et de minimiser le risque d'erreurs.</p><p>Par exemple, un utilisateur peut utiliser les requêtes récentes dans l'éditeur ES|QL dans Discover (et les mettre en vedette) :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt49033a46a0805ec8/6a17f321e9ea87a505a9c724/eb0f9fe37b92dec421c394d31ae7d90afebe062e-1421x793.png" alt="Un exemple d'utilisation des requêtes récentes dans l'éditeur ES|QL dans discover (et comment les démarrer)." /><p>Les requêtes récentes sont intégrées dans le tableau de bord :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta2f7c745cdc5e5f1/6a17f323a2929932a1d02da9/b84cd3a9bdec58812360d2aba4fc7713363ee3cc-1411x797.png" alt=" Les requêtes récentes sont intégrées dans un tableau de bord." /><p>PPL n'offre pas de possibilité comparable, ce qui oblige les utilisateurs à recourir au copier-coller manuel ou à des notes externes pour réutiliser les requêtes. La différence est plus qu'une question de commodité ; elle reflète la stratégie d'Elastic qui consiste à faire d'ES|QL un langage véritablement intégré à l'écosystème Kibana. Avec des fonctionnalités telles que les requêtes récentes, l'éditeur ES|QL ne se contente pas de rationaliser les flux de travail quotidiens, il pose également les bases de fonctionnalités plus avancées, actuellement en phase de prévisualisation technique, ce qui garantit une évolution constante de l'expérience.</p><h2>Conclusion</h2><p>ES|QL est plus qu'une syntaxe ; elle reflète la stratégie d'Elastic visant à améliorer la façon dont les utilisateurs recherchent, explorent et analysent les données. Grâce à une autocomplétion intelligente, à des requêtes recommandées en fonction du contexte, à des conseils intégrés à l'éditeur et à des outils comme Inspect, l'éditeur ES|QL accélère l'apprentissage, réduit les erreurs et simplifie les flux de travail complexes tels que l'analyse croisée des clusters. Intégré à Kibana, il relie de manière transparente les requêtes aux tableaux de bord, aux alertes et aux visualisations pour un flux de travail ininterrompu.</p><p>En résumé, ES|QL n'est pas simplement un autre langage pipé ; il s'agit d'un moteur de requêtes bien pensé associé à une interface utilisateur intuitive qui redéfinit fondamentalement la façon dont vous interagissez avec vos données, en offrant une expérience intégrée, intelligente et en constante évolution qui contraste fortement avec la nature souvent séquentielle et moins guidée d'OpenSearch PPL.</p><h2>Prochaines étapes</h2><p>Ce blog ne fait qu'effleurer la surface d'ES|QL. Les prochains articles approfondiront les comparaisons avec OpenSearch PPL et exploreront les fonctionnalités géospatiales, de visualisation et les futures fonctionnalités de l'éditeur telles que les <a href="https://www.elastic.co/docs/explore-analyze/dashboards/add-controls">contrôles</a> (déjà disponibles dans les tableaux de bord), les onglets d'exploration multi-données, la recherche en arrière-plan, l'historique des requêtes plus riche et FUSE.</p><h2>Essayez ES|QL dès aujourd'hui</h2><p>Vous pouvez tester ES|QL dans des projets <a href="https://www.elastic.co/cloud/serverless">Serverless</a> Elasticsearch entièrement gérés avec un <a href="https://www.elastic.co/docs/deploy-manage/deploy/elastic-cloud/create-serverless-project">essai gratuit</a>. Il est également disponible dans les versions à partir de la 8.11, mais c'est dans les versions <a href="https://www.elastic.co/blog/whats-new-elastic-9-1-0">8.19 et 9.1</a> qu'il est le plus utile.</p><p>Démarrez en quelques minutes sur votre environnement local à l'aide d'une simple commande :</p>curl -fsSL https://elastic.co/start-local | sh]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/opensearch-vs-elasticsearch-ppl-esql</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/opensearch-vs-elasticsearch-ppl-esql</guid>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Libby Lin,George Kobar]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte51b193824ff8084/6a17f3257f6f154b7bc09c7c/f1ff4ff4a00b3e5b084d4116cea6cabc82a2d816-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 18 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Présentation du générateur de requêtes ES|QL pour le client Elasticsearch Ruby]]></title>
    <description><![CDATA[Apprenez à utiliser le constructeur de requêtes ES|QL récemment publié pour le client Elasticsearch Ruby. Un outil pour construire des requêtes ES|QL plus facilement avec du code Ruby.]]></description>
    <content:encoded><![CDATA[<p>Nous avons récemment publié <a href="https://github.com/elastic/esql-ruby/"><code>elastic-esql</code></a>, un outil Ruby publié sous licence Apache 2. Cette gemme vous permet de construire les requêtes <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/esql">ES|QL</a> d'Elastic en Ruby idiomatique, que vous pouvez ensuite utiliser avec l'API de requête ES|QL. ES|QL permet aux développeurs de filtrer, de transformer et d'analyser les données stockées dans Elasticsearch au moyen de requêtes. Il utilise les tuyaux "" ( <code>|</code> ) pour travailler avec les données étape par étape. La gem utilise des fonctions Ruby à la place, que vous pouvez enchaîner à l'objet original pour construire des requêtes plus complexes :</p><p><strong>ESQL :</strong></p><p><strong>Rubis :</strong></p>Elastic::ESQL.from('sample_data').limit(2).sort('@timestamp').descending<h2>Installation</h2><p>La gemme peut être installée à partir de RubyGems avec :</p>gem install elastic-esql<p>Il peut également être ajouté au fichier Gemfile d'un projet :</p>gem 'elastic-esql'<h2>Utilisation</h2><p>Vous pouvez soit construire une requête complète en une seule fois, soit créer un objet de requête à l'aide d'une commande source telle que <code>from</code> ou <code>row</code>, puis enchaîner les méthodes ES|QL pour construire à partir de cet objet.</p>query = Elastic::ESQL.from('sample_data')
query.limit(2).sort('@timestamp')<p>La gemme traduit le code en ES|QL dans la méthode <code>to_s</code>, de sorte qu'elle renvoie la requête ES|QL lorsqu'elle est imprimée ou transformée en chaîne :</p>query = Elastic::ESQL.from('sample_data').limit(2).sort('@timestamp').descending
query.to_s
# =&gt; "FROM sample_data | LIMIT 2 | SORT @timestamp DESC"<p>Vous pouvez instancier un objet de requête et modifier son état initial en utilisant les équivalents <code>!</code> de chaque fonction :</p>query = Elastic::ESQL.from('sample_data')
query.to_s
# =&gt; "FROM sample_data"
query.limit!(2).sort!('@timestamp')
query.to_s
# =&gt; "FROM sample_data | LIMIT 2 | SORT @timestamp"<p>L'outil offre des moyens pratiques d'enchaîner des étapes supplémentaires à une fonction ES|QL, comme <code>enrich</code> et <code>sort</code>. Une fois que vous avez appelé <code>enrich</code> sur un objet <code>Elastic::ESQL</code>, vous pouvez enchaîner <code>on</code> et <code>with</code>:</p>esql.enrich!('policy').on('a').with({ name: 'language_name' })<p>Vous pouvez également enchaîner <code>desc</code>, <code>asc</code>, <code>nulls_first</code> et <code>nulls_last</code> à votre requête après avoir utilisé <code>sort</code>:</p>Elastic::ESQL.from('sample_data').sort('@timestamp').asc.to_s
# =&gt; 'FROM sample_data | SORT @timestamp ASC'

Elastic::ESQL.from('sample_data').sort('@timestamp').desc.nulls_first.to_s
# =&gt; 'FROM sample_data | SORT @timestamp DESC NULLS FIRST'<p>Elle prend également en charge les chaînes personnalisées, au cas où vous souhaiteriez écrire vous-même la requête ES|QL ou utiliser une fonctionnalité qui n'a pas encore été ajoutée à la bibliothèque. <code>custom</code> joindra les chaînes à la fin de la requête. Il les ajoutera au fur et à mesure qu'ils sont envoyés à la fonction, sans ajouter de caractères de liaison. Ils seront combinés au reste de la requête par un caractère d'espacement.</p>esql = Elastic::ESQL.from('sample_data')
esql.custom('| MY_VALUE = "test value"').to_s
# =&gt; 'FROM sample_data | MY_VALUE = "test value"'<p>Vous pouvez également enchaîner les fonctions de <code>custom</code>:</p>esql.custom('| MY_VALUE = "test value"').custom('| ANOTHER, VALUE')
'FROM sample_data | MY_VALUE = "test value" | ANOTHER, VALUE'<h2>Utilisation du générateur de requêtes ES|QL avec le client Ruby</h2><p>Vous pouvez utiliser le constructeur de requêtes directement avec <a href="https://github.com/elastic/elasticsearch-ruby">elasticsearch-ruby</a> et l'API <code>esql.query</code> en envoyant l'objet de requête :</p>require 'elasticsearch'
require 'elastic/esql'

client = Elasticsearch::Client.new
index = 'sample_data'

query = Elastic::ESQL.from(index)
                     .sort('@timestamp')
                     .desc
                     .where('event_duration &gt; 5000000')
                     .limit(3)
                     .eval({ duration_ms: 'ROUND(event_duration/1000000.0, 1)' })
client.esql.query(body: { query: query })<p>Vous pouvez également l'utiliser avec l'ES|QL Helper du client Elasticsearch Ruby, pour en <a href="https://www.elastic.co/search-labs/blog/esql-ruby-helper-elasticsearch">savoir plus :</a></p>require 'elasticsearch/helpers/esql_helper'

Elasticsearch::Helpers::ESQLHelper.query(client, query)<h2>En tant qu'outil autonome</h2><p>La gemme est conçue comme un outil autonome pour construire des requêtes ES|QL de manière idiomatique. Il n'a aucune dépendance d'exécution ; vous pouvez l'utiliser avec le client Ruby officiel d'Elasticsearch, ou seul.</p><p>La requête générée peut être utilisée avec l'API <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-esql-query"><code>esql.query</code></a> de toutes les façons dont une application interagit avec l'API Elasticsearch (Ruby ou non). Une fois qu'une requête est construite avec <code>elastic-esql</code>, la chaîne générée peut être envoyée à l'API en tant que paramètre <code>query</code> dans le corps de la requête. </p><p>J'ai déjà écrit sur l'<a href="https://www.elastic.co/search-labs/blog/elasticsearch-ruby-tools">utilisation d'Elasticsearch avec des outils Ruby populaires.</a> Cette gemme peut être utilisée avec n'importe quel outil Ruby populaire pour interroger Elasticsearch avec ES|QL.</p><h2>Conclusion</h2><p>Cette bibliothèque est en cours de développement et l'API finale n'a pas encore été finalisée. Il s'agit actuellement d'un aperçu technique. Si vous avez des commentaires sur l'API actuelle ou sur son utilisation générale, n'hésitez pas à <a href="https://github.com/elastic/esql-ruby/issues">ouvrir un nouveau dossier.</a> Veuillez vous référer au <a href="https://github.com/elastic/esql-ruby/?tab=readme-ov-file#ruby-esql-query-builder">README</a> pour en savoir plus sur Ruby ES|QL Query Builder.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-query-builder-elasticsearch-ruby-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-query-builder-elasticsearch-ruby-client</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[Ruby]]></category>
    <dc:creator><![CDATA[Fernando Briano]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt85d112ccca541b9e/6a17dccb4b055d6bfd4320cc/f8e1263ab53d356824a4fc539084151be80899db-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 17 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Ingérer des données géospatiales dans Elasticsearch avec Kibana pour les utiliser dans ES|QL]]></title>
    <description><![CDATA[Comment utiliser Kibana et le processeur d'ingestion csv pour ingérer des données géospatiales dans Elasticsearch afin de les utiliser pour la recherche dans Elasticsearch Query Language (ES|QL). Elasticsearch possède de puissantes fonctionnalités de recherche géospatiale, qui sont désormais intégrées à ES|QL pour une facilité d'utilisation et une familiarité avec l'OGC considérablement améliorées. Mais pour utiliser ces fonctionnalités, nous avons besoin de données géospatiales.]]></description>
    <content:encoded><![CDATA[<p>Nous avons récemment publié un blog décrivant comment utiliser les nouvelles <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">fonctionnalités</a> <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">de recherche géospatiale</a> <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">dans ES|QL,</a> le nouveau et puissant <a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga">langage de requête par pipeline</a> d' Elasticsearch. Pour utiliser ces fonctionnalités, vous devez disposer de données géospatiales dans Elasticsearch. Dans ce blog, nous allons donc vous montrer comment ingérer des données géospatiales et comment les utiliser dans des requêtes ES|QL.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc041ebca11476c6/6a16f70560084b31b93c4344/01fde3b1d714f12bf8673140c9f2f940d443de31-1440x823.jpg" alt="Recherche géospatiale ESQL" /><h2>Importation de données géospatiales à l'aide de Kibana</h2><p>Les données que nous avons utilisées pour les exemples du blog précédent étaient basées sur les données que nous utilisons en interne pour les tests d'intégration. Pour vous faciliter la tâche, nous l'avons inclus ici sous la forme de quelques fichiers CSV qui peuvent être facilement importés à l'aide de Kibana. Les données sont un mélange d'aéroports, de villes et de limites de villes. Vous pouvez télécharger les données à partir de :</p><ul><li><p><a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airports.csv">aéroports.csv</a></p><ul><li><p>Il s'agit d'une fusion de trois ensembles de données :</p><ul><li><p>Aéroports (noms, emplacements et données connexes) de <a href="https://www.naturalearthdata.com/downloads/10m-cultural-vectors/airports/">Natural Earth</a></p></li><li><p>Localisation des villes à partir de <a href="https://simplemaps.com/data/world-cities">SimpleMaps</a></p></li><li><p>Élévations des aéroports à partir de la <a href="https://www.partow.net/miscellaneous/airportdatabase/">base de données mondiale des aéroports</a></p></li></ul></li></ul></li><li><p><a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airport_city_boundaries.csv">limites_de_la_ville_de_l'aeroport.csv</a></p><ul><li><p>Il s'agit d'une fusion des noms d'aéroports et de villes ci-dessus avec une nouvelle source :</p><ul><li><p>Limites de la ville d'après <a href="https://www.openstreetmap.org/">OpenStreetMap</a></p></li></ul></li></ul></li></ul><p>Comme vous pouvez le deviner, nous avons passé un certain temps à combiner ces sources de données dans les deux fichiers ci-dessus, dans le but de pouvoir tester les fonctionnalités géospatiales d'ES|QL. Il se peut que cela ne corresponde pas tout à fait à vos besoins spécifiques en matière de données, mais j'espère que cela vous donnera une idée de ce qui est possible. En particulier, nous voulons démontrer quelques points intéressants :</p><ul><li><p>Importation de données contenant des champs géospatiaux avec d'autres données indexables</p></li><li><p>Importer les données <code>geo_point</code> et <code>geo_shape</code> et les utiliser ensemble dans les requêtes</p></li><li><p>Importation de données dans deux index qui peuvent être reliés à l'aide d'une relation spatiale</p></li><li><p>Création d'un pipeline d'ingestion pour faciliter les importations futures (au-delà de Kibana)</p></li><li><p>Quelques exemples de processeurs d'acquisition, tels que <code>csv</code>, <code>convert</code> et <code>split</code></p></li></ul><p>Bien que nous parlions de travailler avec des données CSV dans ce blog, il est important de comprendre qu'il y a <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">plusieurs façons d</a> <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">'</a> <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">ajouter des données géographiques en utilisant</a> <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">Kibana</a>. Dans l'application Carte, vous pouvez télécharger des données délimitées telles que CSV, GeoJSON et ESRI ShapeFiles et vous pouvez également dessiner des formes directement dans la carte. Pour ce blog, nous nous concentrerons sur l'importation de fichiers CSV à partir de la page d'accueil de Kibana.</p><h3>Importation des aéroports</h3><p>Le premier fichier, <a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airports.csv">airports.csv,</a> a quelques particularités intéressantes avec lesquelles nous devons composer. Tout d'abord, les colonnes sont séparées par des espaces blancs supplémentaires, ce qui n'est pas typique des fichiers CSV. Deuxièmement, le champ <code>type</code> est un champ à valeurs multiples, que nous devons diviser en champs distincts. Enfin, certains champs ne sont pas des chaînes de caractères et doivent être convertis dans le bon type. Tout cela peut être fait en utilisant la fonction d'importation CSV de Kibana.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt393bc416bf425301/6a16f707839dfa1e86dcfca9/b1afd8c95973bec32f229a9adfaef14680b09a8e-1944x478.png" alt="Kibana Upload - Aperçu" /><p>Commencez par la page d'accueil de Kibana. Une section intitulée "Get started by adding integrations" contient un lien intitulé "Upload a file":</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte12fc741edab20d3/6a16f709acf088600fbe98bf/996372bb3a52859cc840bd1d8f984a33a0e7ada3-1180x410.png" alt="Kibana Home - Télécharger un fichier" /><p>En cliquant sur ce lien, vous accéderez à la page "Upload file". Ici, vous pouvez faire glisser et déposer le fichier <code>airports.csv</code>, et Kibana analysera le fichier et vous présentera un aperçu des données. Il aurait dû détecter automatiquement que le délimiteur était une virgule et que la première ligne était la ligne d'en-tête. Cependant, il n'a probablement pas supprimé les espaces blancs supplémentaires entre les colonnes, ni déterminé les types de champs, en supposant que tous les champs sont soit <code>text</code>, soit <code>keyword</code>. Nous devons y remédier.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf65a09ec0c7a61ad/6a16f70ad7c0227aedde626f/1d9ffa6cdbc0d67a228be1a747ec1ebda6a63099-1800x538.png" alt="Kibana Upload - Aperçu" /><p>Cliquez sur <code>Override settings</code> et cochez les cases <code>Should trim fields</code> et <code>Apply</code> pour fermer les paramètres. Nous devons maintenant fixer les types de champs. Elle est disponible à la page suivante, alors cliquez sur <code>Import</code>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltda9a5f85d8e693dc/6a16f70c60084b72f53c4348/a97aceffb1858eae26a213336913505ae9923b03-1800x526.png" alt="Kibana Upload - Importation" /><p>Choisissez d'abord un nom d'index, puis sélectionnez <code>Advanced</code> pour accéder à la page des mappages de champs et du processeur d'ingestion.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt56705083cdd9eb18/6a16f70d66c4f93350f8bdbb/058b0fb09da0b8d7f9c9b0a9c83b8b485ce43925-1440x629.png" alt="Kibana Upload - Correspondance des champs" /><p>Ici, nous devons apporter des modifications aux mappages de champs pour l'index, ainsi qu'au pipeline d'ingestion pour l'importation des données. Tout d'abord, alors que Kibana a probablement auto-détecté le champ <code>scalerank</code> comme étant <code>long</code>, il a perçu par erreur les champs <code>location</code> et <code>city_location</code> comme étant <code>keyword</code>. Modifiez-les à l'adresse <code>geo_point</code>, et vous obtiendrez des correspondances qui ressembleront à quelque chose de semblable :</p>{
  "properties": {
    "abbrev":        { "type": "keyword" },
    "city":          { "type": "keyword" },
    "city_location": { "type": "geo_point" },
    "country":       { "type": "keyword" },
    "elevation":     { "type": "double" },
    "location":      { "type": "geo_point" },
    "name":          { "type": "text" },
    "scalerank":     { "type": "long" },
    "type":          { "type": "keyword" }
  }
}<p>Vous disposez d'une certaine marge de manœuvre, mais sachez que le type de champ choisi aura une incidence sur la manière dont il sera indexé et sur le type de requêtes possibles. Par exemple, si vous laissez <code>location</code> comme <code>keyword</code>, vous ne pouvez pas effectuer de recherches géospatiales sur ce site. De même, si vous laissez <code>elevation</code> en tant que <code>text</code>, vous ne pouvez pas effectuer de requêtes sur les plages numériques.</p><p>Il est maintenant temps de réparer le pipeline d'ingestion. Si Kibana a détecté automatiquement <code>scalerank</code> comme <code>long</code> ci-dessus, il aura également ajouté un processeur pour convertir le champ en <code>long</code>. Nous devons ajouter un processeur similaire pour le champ <code>elevation</code>, en le convertissant cette fois en <code>double</code>. Modifiez le pipeline pour vous assurer que cette conversion est en place. Avant de l'enregistrer, nous souhaitons effectuer une autre conversion, afin de diviser le champ <code>type</code> en plusieurs champs. Ajouter un processeur <code>split</code> au pipeline, avec la configuration suivante :</p>{
  "split": {
    "field": "type",
    "separator": ":",
    "ignore_missing": true
  }
}<p>Le pipeline d'ingestion final devrait ressembler à ceci :</p>{
  "description": "Ingest pipeline created by text structure finder",
  "processors": [
    {
      "csv": {
        "field": "message",
        "target_fields": [
          "abbrev",
          "name",
          "scalerank",
          "type",
          "location",
          "country",
          "city",
          "city_location",
          "elevation"
        ],
        "ignore_missing": false,
        "trim": true
      }
    },
    {
      "convert": {
        "field": "scalerank",
        "type": "long",
        "ignore_missing": true
      }
    },
    {
      "convert": {
        "field": "elevation",
        "type": "double",
        "ignore_missing": true
      }
    },
    {
      "split": {
        "field": "type",
        "separator": ":",
        "ignore_missing": true
      }
    },
    {
      "remove": {
        "field": "message"
      }
    }
  ]
}<p>Notez que nous n'avons pas ajouté de processeur de conversion pour les champs <code>location</code> et <code>city_location</code>. Cela s'explique par le fait que le type <code>geo_point</code> dans la correspondance des champs comprend déjà le format WKT des données de ces champs. Le type <code>geo_point</code> peut comprendre une série de formats, notamment <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html">WKT, GeoJSON, etc</a>. Si nous avions, par exemple, deux colonnes dans le fichier CSV pour <code>latitude</code> et <code>longitude</code>, nous aurions dû ajouter un processeur <code>script</code> ou <code>set</code> pour les combiner en un seul champ <code>geo_point</code> (par exemple. <code>"set": {"field": "location", "value": "{{lat}},{{lon}}"}</code>).</p><p>Nous sommes maintenant prêts à importer le fichier. Cliquez sur <code>Import</code> et les données seront importées dans l'index avec les mappings et le pipeline d'ingestion que nous venons de définir. Si des erreurs surviennent lors de l'ingestion des données, Kibana les signale ici, afin que vous puissiez modifier les données sources ou le pipeline d'ingestion et réessayer.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte81621425c7289c5/6a16f70f839dfaf608dcfcad/55dde2940c7aba66ce8257d15007ef797b8a5107-1440x415.png" alt="Kibana Upload - Importation" /><p>Remarquez qu'une nouvelle ligne d'ingestion a été créée. Il peut être consulté en allant dans la section <code>Stack Management</code> de Kibana, et en sélectionnant <code>Ingest pipelines</code>. Ici, vous pouvez voir le pipeline que nous venons de créer et le modifier si nécessaire. En fait, la section <code>Ingest pipelines</code> peut être utilisée pour créer et tester des pipelines d'ingestion, une fonctionnalité très utile si vous prévoyez d'effectuer des ingérences encore plus complexes.</p><p>Si vous souhaitez explorer ces données immédiatement, passez aux sections suivantes, mais si vous souhaitez également importer les limites des villes, continuez à lire.</p><h3>Importation des limites de la ville</h3><p>Le fichier des limites des villes disponible à l'adresse <a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airport_city_boundaries.csv">airport_city_boundaries.csv</a> est un peu plus simple à importer que l'exemple précédent. Il contient un champ <code>city_boundary</code> qui est une représentation WKT des limites de la ville sous forme de <code>POLYGON</code>, et un champ <code>city_location</code> qui est une représentation <code>geo_point</code> de l'emplacement de la ville. Nous pouvons importer ces données de la même manière que les données aéroportuaires, à quelques différences près :</p><ul><li><p>Nous avons dû sélectionner le paramètre d'annulation <code>Has header row</code> car il n'était pas détecté automatiquement.</p></li><li><p>Nous n'avons pas eu besoin de découper les champs, car les données étaient déjà exemptes d'espaces blancs supplémentaires.</p></li><li><p>Nous n'avons pas eu besoin de modifier le pipeline d'ingestion car tous les types étaient soit des chaînes de caractères, soit des types spatiaux.</p></li><li><p>Nous avons toutefois dû modifier les correspondances entre les champs afin de définir le champ <code>city_boundary</code> comme étant <code>geo_shape</code> et le champ <code>city_location</code> comme étant <code>geo_point</code></p></li></ul><p>Nos mappages de champs finaux se présentaient comme suit :</p>{
  "properties": {
    "abbrev":        { "type": "keyword" },
    "airport":       { "type": "keyword" },
    "city":          { "type": "keyword" },
    "city_boundary": { "type": "geo_shape" },
    "city_location": { "type": "geo_point" },
    "region":        { "type": "text" }
  }
}<p>Comme pour l'importation <code>airports.csv</code>, il suffit de cliquer sur <code>Import</code> pour importer les données dans l'index. Les données seront importées avec les mappings que nous avons édités et le pipeline d'ingestion défini par Kibana.</p><h3>Explorer les données géospatiales avec les outils de développement</h3><p>Dans Kibana, il est habituel d'explorer les données indexées avec "Discover". Cependant, si votre intention est d'écrire votre propre application en utilisant des requêtes ES|QL, il peut être plus intéressant d'essayer d'accéder à l'API Elasticsearch brute. Kibana dispose d'une console pratique pour expérimenter l'écriture de requêtes. Il s'agit de la console <code>Dev Tools</code>, qui se trouve dans la barre latérale de Kibana. Cette console communique directement avec le cluster Elasticsearch et peut être utilisée pour exécuter des requêtes, créer des index, etc.</p><p>Essayez ce qui suit :</p>POST /_query?error_trace=true&amp;format=txt
{
  "query": """
FROM airports
| EVAL distance = ST_DISTANCE(city_location, TO_GEOPOINT("POINT(12.565 55.673)"))
| WHERE distance &lt; 1000000 AND scalerank &lt; 6 AND distance &gt; 10000
| SORT distance ASC
| KEEP distance, abbrev, name, location, country, city, elevation
| LIMIT 10
  """
}<p>Cela devrait donner les résultats suivants :</p><p>distance</p><p>abbrev</p><p>nom</p><p>Lieu</p><p>pays</p><p>ville</p><p>élévation</p><p>273418.05776847183</p><p>HAM</p><p>Hambourg</p><p>POINT (10.005647830925 53.6320011640866)</p><p>Allemagne</p><p>Norderstedt</p><p>17.0</p><p>337534.653466062</p><p>TXL</p><p>Berlin-Tegel Int'l</p><p>POINT (13.2903090925074 52.5544287044101)</p><p>Allemagne</p><p>Hohen Neuendorf</p><p>38.0</p><p>483713.15032266214</p><p>OSL</p><p>Oslo Gardermoen</p><p>POINT (11.0991032762581 60.1935783171386)</p><p>Norvège</p><p>Oslo</p><p>208.0</p><p>522538.03148094116</p><p>BMA</p><p>Bromma</p><p>POINT (17.9456175406145 59.3555902065112)</p><p>Suède</p><p>Stockholm</p><p>15.0</p><p>522538.03148094116</p><p>ARN</p><p>Arlanda</p><p>POINT (17.9307299016916 59.6511203397372)</p><p>Suède</p><p>Stockholm</p><p>38.0</p><p>624274.8274399083</p><p>DHS</p><p>Düsseldorf Int'l</p><p>POINT (6.76494446612174 51.2781820420774)</p><p>Allemagne</p><p>Düsseldorf</p><p>45.0</p><p>633388.6966435644</p><p>PRG</p><p>Ruzyn</p><p>POINT (14.2674849854076 50.1076511703671)</p><p>Tchécoslovaquie</p><p>Prague</p><p>381.0</p><p>635911.1873311149</p><p>AMS</p><p>Schiphol</p><p>POINT (4.76437693232812 52.3089323889822)</p><p>Pays-Bas</p><p>Hoofddorp</p><p>-3.0</p><p>670864.137958866</p><p>FRA</p><p>Francfort Int'l</p><p>POINT (8.57182286907608 50.0506770895207)</p><p>Allemagne</p><p>Francfort</p><p>111.0</p><p>683239.2529970079</p><p>WAW</p><p>Okecie Int'l</p><p>POINT (20.9727263383587 52.171026749259)</p><p>Pologne</p><p>Piaseczno</p><p>111.0</p><h2>Visualiser des données géospatiales avec Kibana Maps</h2><p>Kibana Maps est un outil puissant de visualisation des données géospatiales. Il peut être utilisé pour créer des cartes avec plusieurs couches, chaque couche représentant un ensemble de données différent. Les données peuvent être filtrées, agrégées et stylisées de différentes manières. Dans cette section, nous allons vous montrer comment créer une carte dans Kibana Maps en utilisant les données que nous avons importées dans la section précédente.</p><p>Dans le menu Kibana, naviguez vers <code>Analytics</code>-&gt;<code>Maps</code> pour ouvrir une nouvelle vue de la carte. Cliquez sur <code>Add Layer</code> et sélectionnez <code>Documents</code>, choisissez la vue de données <code>airports</code> et modifiez le style de la couche pour colorer les marqueurs à l'aide du champ <code>elevation</code>, de sorte que nous puissions facilement voir à quelle hauteur se trouve chaque aéroport.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcc4736d88c1abc9/6a16f7102b835f7353f4afca/9e63726d7c059331e6e20e474f8abee53dc2cbb4-840x388.png" alt="Kibana Maps - Style de calque pour les aéroports" /><p>Cliquez sur "Conserver les modifications" pour enregistrer la carte :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ec3cc535b5c21d8/6a16f71375879ec091fe15dc/32ad1dadb5d341a2b66662c58638b781122fc22c-2852x1528.png" alt="Kibana Maps - Aéroports" /><p>Ajoutez maintenant une deuxième couche, en sélectionnant cette fois la vue de données <code>airport_city_boundaries</code>. Cette fois-ci, nous utiliserons le champ <code>city_boundary</code> pour styliser le calque et définir la couleur de remplissage sur un bleu clair. Les limites de la ville apparaissent alors sur la carte. Veillez à réorganiser les couches de manière à ce que les marqueurs d'aéroport soient placés en haut.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2932d7ff4a7206c9/6a16f7156f7f0409f09145c7/53dd65026f9a98c13f2cc4f9328a79242f0b70de-2854x1510.png" alt="Kibana Maps - Style de calque pour les limites des villes" /><h2>Jointures spatiales</h2><p>ES|QL ne prend pas en charge les commandes <code>JOIN</code>, mais vous pouvez réaliser un cas spécial de jointure à l'aide de la <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich">commande</a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich"><code>ENRICH</code></a>. Cette commande s'apparente à une "jointure gauche" en SQL, vous permettant d'enrichir les résultats d'un index avec des données d'un autre index sur la base d'une relation spatiale entre les deux ensembles de données.</p><p>Par exemple, enrichissons les résultats d'un tableau d'aéroports avec des informations supplémentaires sur la ville qu'ils desservent en trouvant la limite de la ville qui contient l'emplacement de l'aéroport, puis effectuons quelques statistiques sur les résultats :</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
| STATS
    centroid = ST_CENTROID_AGG(location),
    count = COUNT(city_location)
    BY region
| SORT count DESC
| LIMIT 10<p>Si vous exécutez cette requête sans avoir au préalable préparé l'index enrichi, vous obtiendrez un message d'erreur du type</p>cannot find enrich policy [city_boundaries]<p>En effet, comme nous l'avons déjà mentionné, ES|QL ne prend pas en charge les véritables commandes <code>JOIN</code>. L'une des raisons principales est qu'Elasticsearch est un système distribué et que les jointures sont des opérations coûteuses qu'il peut être difficile de faire évoluer. Cependant, la commande <code>ENRICH</code> peut être très efficace, car elle utilise des index enrichis spécialement préparés qui sont dupliqués sur l'ensemble du cluster, ce qui permet d'effectuer des jointures locales sur chaque nœud.</p><p>Pour mieux comprendre, concentrons-nous sur la commande <code>ENRICH</code> dans la requête ci-dessus :</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary<p>Cette commande demande à Elasticsearch d'enrichir les résultats extraits de l'index <code>airports</code> et d'effectuer une jointure <code>intersects</code> entre le champ <code>city_location</code> de l'index original et le champ <code>city_boundary</code> de l'index <code>airport_city_boundaries</code>, que nous avons utilisé dans quelques exemples plus tôt. Mais certaines de ces informations ne sont pas clairement visibles dans cette requête. Ce que nous voyons, c'est le nom d'une politique d'enrichissement <code>city_boundaries</code>, et l'information manquante est encapsulée dans cette définition de politique.</p>{
  "geo_match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}<p>Ici, nous pouvons voir qu'il effectuera une requête <code>geo_match</code> (<code>intersects</code> est la valeur par défaut), que le champ à comparer est <code>city_boundary</code> et que les champs <code>enrich_fields</code> sont les champs que nous voulons ajouter au document d'origine. L'un de ces champs, le <code>region</code>, a été utilisé comme clé de regroupement pour la commande <code>STATS</code>, ce que nous n'aurions pas pu faire sans cette capacité de "jointure à gauche". Pour plus d'informations sur les politiques d'enrichissement, voir la <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-setup.html">documentation d'enrichissement</a>.</p><p>Les index et politiques d'enrichissement d'Elasticsearch ont été conçus à l'origine pour enrichir les données au moment de l'indexation, en utilisant les données d'un autre index d'enrichissement préparé. Dans ES|QL, cependant, la commande <code>ENRICH</code> fonctionne au moment de la requête et ne nécessite pas l'utilisation de pipelines d'ingestion. Cela le rend assez similaire à un SQL <code>LEFT JOIN</code>, sauf que vous ne pouvez pas joindre deux index, mais seulement un index normal à gauche avec un index enrichi spécialement préparé à droite.</p><p>Dans les deux cas, que ce soit pour les pipelines d'ingestion ou pour l'utilisation dans ES|QL, il est nécessaire d'effectuer quelques étapes préparatoires pour mettre en place l'index et la politique d'enrichissement. Nous avons déjà importé l'index <code>airport_city_boundaries</code> ci-dessus, mais il n'est pas directement utilisable comme index d'enrichissement dans la commande <code>ENRICH</code>. Nous devons d'abord effectuer deux démarches :</p><ul><li><p>Créez la politique d'enrichissement décrite ci-dessus pour définir l'index source, le champ de l'index source à comparer et les champs à renvoyer une fois la correspondance établie.</p></li><li><p>Exécutez cette politique pour créer l'index d'enrichissement. Cela permet de construire un index interne spécial, en lisant l'index source d'origine dans une structure de données plus efficace qui est copiée à travers le cluster.</p></li></ul><p>La politique d'enrichissement peut être créée à l'aide de la commande suivante :</p>PUT /_enrich/policy/city_boundaries
{
  "match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}<p>La politique peut être exécutée à l'aide de la commande suivante :</p>POST /_enrich/policy/city_boundaries/_execute<p>Notez que si vous modifiez le contenu de l'index <code>airport_city_boundaries</code>, vous devrez réexécuter cette politique pour que les changements soient reflétés dans l'index enrichi. Exécutons à nouveau la requête ES|QL d'origine :</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
| STATS
    centroid = ST_CENTROID_AGG(location),
    count = COUNT(city_location)
    BY region
| SORT count DESC
| LIMIT 10<p>Cette méthode permet d'obtenir les 5 régions qui comptent le plus d'aéroports, ainsi que le centroïde de tous les aéroports qui ont des régions correspondantes et la longueur de la représentation WKT des limites des villes à l'intérieur de ces régions :</p><p>centroïde</p><p>Compte</p><p>région</p><p>POINT (-12.139086859300733 31.024386116624648)</p><p>126</p><p>nul</p><p>POINT (-83.10398317873478 42.300230911932886)</p><p>3</p><p>Détroit</p><p>POINT (39.74537850357592 47.21613017376512)</p><p>3</p><p>городской округ Батайск</p><p>POINT (-156.80986787192523 20.476673701778054)</p><p>3</p><p>Hawaï</p><p>POINT (-73.94515332765877 40.70366442203522)</p><p>3</p><p>Ville de New York</p><p>POINT (-83.10398317873478 42.300230911932886)</p><p>3</p><p>Détroit</p><p>POINT (-76.66873019188643 24.306286952923983)</p><p>2</p><p>New Providence</p><p>POINT (-3.0252167768776417 51.39245774131268)</p><p>2</p><p>Cardiff</p><p>POINT (-115.40993484668434 32.73126147687435)</p><p>2</p><p>Municipalité de Mexicali</p><p>POINT (41.790108773857355 50.302146775648)</p><p>2</p><p>Центральный район</p><p>POINT (-73.88902732171118 45.57078813901171)</p><p>2</p><p>Montréal</p><p>Vous pouvez également remarquer que la région la plus fréquemment trouvée est <code>null</code>. Qu'est-ce que cela peut signifier ? Rappelez-vous que j'ai comparé cette commande à une "jointure gauche" en SQL, ce qui signifie que si aucune limite de ville correspondante n'est trouvée pour un aéroport, l'aéroport est toujours renvoyé, mais avec les valeurs <code>null</code> pour les champs de l'index <code>airport_city_boundaries</code>. Il s'avère que 125 aéroports n'ont pas trouvé de correspondance avec <code>city_boundary</code>, et un aéroport avec une correspondance où le champ <code>region</code> était <code>null</code>. Cela a conduit à un décompte de 126 aéroports sans <code>region</code> dans les résultats. Si votre cas d'utilisation exige que tous les aéroports puissent être mis en correspondance avec les limites d'une ville, il faudra trouver des données supplémentaires pour combler les lacunes. Il serait nécessaire de déterminer deux choses :</p><ul><li><p>les enregistrements de l'index <code>airport_city_boundaries</code> qui n'ont pas de champs <code>city_boundary</code></p></li><li><p>les enregistrements de l'index <code>airports</code> qui ne correspondent pas à l'aide de la commande <code>ENRICH</code> (c'est-à-dire. ne se croisent pas)</p></li></ul><h2>Utilisation de ES|QL pour les données géospatiales dans Kibana Maps</h2><p>Kibana a ajouté la prise en charge de Spatial ES|QL dans l'application Maps. Cela signifie que vous pouvez désormais utiliser ES|QL pour rechercher des données géospatiales dans Elasticsearch et visualiser les résultats sur une carte.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91922eb4ef43d290/6a16f7161949f737bfe7a7b5/bd78470bd8a4bc60f0db7006bd804b8fe87e2fea-1440x683.png" alt="Couches Kibana ES|QL" /><p>Il existe une nouvelle option de couche dans le menu d'ajout de couches, appelée "ES|QL". Comme toutes les fonctions géospatiales décrites jusqu'à présent, il s'agit d'un aperçu technique "" . Cette option permet d'ajouter une couche à la carte en fonction des résultats d'une requête ES|QL. Par exemple, vous pouvez ajouter une couche à la carte qui montre tous les aéroports du monde.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5185ef7461d7e81d/6a16f718839dfa1559dcfcb1/1dd28d3d0509f92d26b0bb5320a2925f7a54c5d9-1440x736.png" alt="Kibana ES|QL - Aéroports" /><p>Vous pouvez également ajouter une couche qui montre les polygones de l'index <code>airport_city_boundaries</code> ou, mieux encore, la requête complexe <code>ENRICH</code> ci-dessus qui génère des statistiques sur le nombre d'aéroports dans chaque région.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ee3543bb811d98/6a16f71a8b73cbbe63189df1/679a0a401faa613c7cedddd07c64f614ac2b7144-1440x727.png" alt="Kibana ES|QL - Statistiques par région" /><h2>Et ensuite ?</h2><p>Le précédent blog sur <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">la recherche géospatiale</a> s'est concentré sur l'utilisation de fonctions telles que <code>ST_INTERSECTS</code> pour effectuer des recherches, disponibles dans Elasticsearch depuis la version 8.14. Ce blog vous montre comment importer les données que nous avons utilisées pour ces recherches. Cependant, Elasticsearch 8.15 a été doté d'une fonction particulièrement intéressante : <code>ST_DISTANCE</code> qui peut être utilisée pour effectuer des recherches de distance spatiale efficaces, et ce sera le sujet du prochain blog !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/geospatial-data-ingest-for-esql</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/geospatial-data-ingest-for-esql</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Craig Taverner]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc041ebca11476c6/6a16f70560084b31b93c4344/01fde3b1d714f12bf8673140c9f2f940d443de31-1440x823.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 25 Oct 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Recherche géospatiale Elasticsearch avec ES|QL]]></title>
    <description><![CDATA[Recherche géospatiale dans le langage de requête Elasticsearch (ES|QL). Elasticsearch possède de puissantes fonctionnalités de recherche géospatiale, qui sont désormais intégrées à ES|QL pour une facilité d'utilisation et une familiarité avec l'OGC considérablement améliorées.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch dispose depuis de nombreuses années de puissantes <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geospatial-analysis.html">fonctionnalités de recherche et d'analyse géospatiales</a>, mais l'API était très différente de celle à laquelle les utilisateurs de SIG étaient habitués. L'année dernière, nous avons <a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga">ajouté le langage d'interrogation ES|QL</a>, un langage d'interrogation par pipeline aussi facile, voire plus facile, que SQL. Il est particulièrement adapté aux cas d'utilisation de la recherche, de la sécurité et de l'observabilité dans lesquels Elastic excelle. Nous avons également ajouté la prise en charge de la recherche et de l'analyse géospatiales dans ES|QL, ce qui facilite grandement son utilisation, en particulier pour les utilisateurs issus des communautés SQL ou <a href="https://en.wikipedia.org/wiki/Geographic_information_system">GIS</a>.</p><p>Elasticsearch 8.12 et 8.13 ont apporté une prise en charge de base des types géospatiaux à ES|QL. Cette fonction a été considérablement améliorée par l'ajout de capacités de recherche géospatiale dans la version 8.14. Plus important encore, ce support a été conçu pour se conformer étroitement à la norme <a href="https://en.wikipedia.org/wiki/Simple_Features">Simple Feature Access de</a> l'<a href="https://en.wikipedia.org/wiki/Open_Geospatial_Consortium">Open Geospatial Consortium (OGC)</a> utilisée par d'autres bases de données spatiales comme PostGIS, ce qui le rend beaucoup plus facile à utiliser pour les experts SIG familiarisés avec ces normes.</p><p>Dans ce blog, nous vous montrerons comment utiliser ES|QL pour effectuer des recherches géospatiales, et comment il se compare aux équivalents SQL et Query DSL. Nous vous montrerons également comment utiliser ES|QL pour effectuer des jointures spatiales et comment visualiser les résultats dans Kibana Maps. Notez que toutes les fonctionnalités décrites ici figurent dans l'aperçu technique de "" , et nous serions ravis de recevoir vos commentaires sur la manière dont nous pouvons les améliorer.</p><h2>Recherche de données géospatiales</h2><p>Commençons par un exemple de requête :</p>FROM airport_city_boundaries
| WHERE ST_INTERSECTS(
      city_boundary,
      "POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))"::geo_shape
  )
| KEEP abbrev, airport, region, city, city_location
<p>Cette opération permet de rechercher tous les polygones de limite de ville qui recoupent un polygone de recherche rectangulaire autour de l'aéroport international de Sanya Phoenix (SYX).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3897df6bed5d6061/6a17d7c2abe0f29eccdfe861/e48bac8f246c8842f2ea97ddd54910045262aeb1-1440x808.png" alt="Recherche géospatiale ESQL" /><p>Dans un échantillon de données d'aéroports, de villes et de limites de villes, cette recherche trouve le polygone d'intersection et renvoie les champs souhaités à partir du document correspondant :</p><p>abbrev</p><p>aéroport</p><p>région</p><p>ville</p><p>ville_location</p><p>SYX</p><p>Sanya Phoenix Int'l</p><p>天涯区</p><p>Sanya</p><p>POINT(109.5036 18.2533)</p><p>C'était facile ! Comparez maintenant cela au DSL Elasticsearch Query classique pour la même requête :</p>GET /airport_city_boundaries/_search
{
  "_source": ["abbrev", "airport", "region", "city", "city_location"],
  "query": {
    "geo_shape": {
      "city_boundary": {
        "shape": {
          "type": "polygon",
          "coordinates" : [[
            [109.4, 18.1],
            [109.6, 18.1],
            [109.6, 18.3],
            [109.4, 18.3],
            [109.4, 18.1]
          ]]
        }
      }
    }
  }
}
<p>Les deux requêtes sont raisonnablement claires dans leur intention, mais la requête ES|QL ressemble beaucoup à SQL. La même requête dans PostGIS se présente comme suit :</p>SELECT abbrev, airport, region, city, city_location
FROM airport_city_boundaries
WHERE ST_INTERSECTS(
    city_boundary,
    'SRID=4326;POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))'::geometry
);
<p>Reprenez l'exemple de ES|QL. C'est un peu la même chose, non ?</p>FROM airport_city_boundaries
| WHERE ST_INTERSECTS(
      city_boundary,
      "POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))"::geo_shape
  )
| KEEP abbrev, airport, region, city, city_location
<p>Nous avons constaté que les utilisateurs existants de l'API Elasticsearch trouvent ES|QL beaucoup plus facile à utiliser. Nous pensons que les utilisateurs de SQL, en particulier ceux de Spatial SQL, trouveront que ES|QL est très proche de ce qu'ils ont l'habitude de voir.</p><h4>Pourquoi pas SQL ?</h4><p>Qu'en est-il d'Elasticsearch SQL ? Il existe depuis un certain temps et possède des fonctions géospatiales. Cependant, Elasticsearch SQL a été écrit comme une enveloppe au-dessus de l'API de requête originale, ce qui signifie que seules les requêtes qui pouvaient être transposées vers l'API originale étaient prises en charge. ES|QL n'a pas cette limitation. Le fait qu'il s'agisse d'une pile entièrement nouvelle permet de nombreuses optimisations qui n'étaient pas possibles avec SQL. Nos benchmarks montrent qu'ES|QL est <a href="https://elasticsearch-benchmarks.elastic.co/#tracks/esql/nightly/default/6M">très souvent plus rapide que l'API Query</a>, en particulier avec les agrégations !</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt18bda964c8b24e36/6a17d7c3e3179155d22d568a/b8b6c2b2e45850d832805ed1e71e522f4955f53c-1440x813.png" alt="polygone-intersection-benchmark" /><h2>Différences avec SQL</h2><p>Il ressort clairement de l'exemple précédent que ES|QL est quelque peu similaire à SQL, mais qu'il existe des différences importantes. Par exemple, ES|QL est un langage d'interrogation par pipeline, qui commence par une commande source telle que FROM et enchaîne toutes les commandes suivantes à l'aide du caractère de pipeline |. Il est ainsi très facile de comprendre comment chaque commande reçoit un tableau de données et effectue une action sur ce tableau, comme le filtrage avec <code>WHERE</code>, l'ajout de colonnes avec <code>EVAL</code>, ou l'exécution d'agrégations avec <code>STATS</code>. Plutôt que de commencer par <code>SELECT</code> pour définir les colonnes de sortie finales, il peut y avoir une ou plusieurs commandes <code>KEEP</code>, la dernière spécifiant les résultats de sortie finaux. Cette structure simplifie le raisonnement sur la requête.</p><p>Si l'on se concentre sur la commande <code>WHERE</code> dans l'exemple ci-dessus, on constate qu'elle ressemble beaucoup à l'exemple PostGIS :</p><p><em>ES|QL</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    "POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))"::geo_shape
)
<p><em>PostGIS</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    'SRID=4326;POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))'::geometry
)
<p>Outre la différence entre les caractères de citation des chaînes, la plus grande différence réside dans la façon dont nous transformons la chaîne de caractères en un type spatial. Dans PostGIS, nous utilisons le suffixe <code>::geometry</code>, tandis que dans ES|QL, nous utilisons le suffixe <code>::geo_shape</code>. En effet, ES|QL fonctionne au sein d'Elasticsearch, et l'opérateur de conversion de type <code>::</code> peut être utilisé pour convertir une chaîne en l'un des <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-limitations.html#_supported_types">types ES|QL pris en charge</a>, dans ce cas, un <code>geo_shape</code>. En outre, les types <code>geo_shape</code> et <code>geo_point</code> dans Elasticsearch impliquent le système de coordonnées spatiales connu sous le nom de WGS84, plus communément désigné par le numéro SRID 4326. Dans PostGIS, cela doit être explicite, d'où l'utilisation du préfixe <code>SRID=4326;</code> pour la chaîne WKT. Si ce préfixe est supprimé, le SRID sera fixé à 0, ce qui est plus proche des types Elasticsearch <code>cartesian_point</code> et <code>cartesian_shape</code>, qui ne sont pas liés à un système de coordonnées spécifique.</p><p>ES|QL et PostGIS fournissent également une syntaxe de fonction de conversion de type :</p><p><em>ES|QL</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    TO_GEOSHAPE("POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))")
)
<p><em>PostGIS</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    ST_SetSRID(
      ST_GeomFromText('POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))'),
      4326
    )
)
<h2>Fonctions de l'OGC</h2><p>Elasticsearch 8.14 introduit les quatre fonctions de recherche spatiale de l'OGC suivantes :</p><p>ES|QL</p><p>PostGIS</p><p>Description</p><p>ST_INTERSECTS</p><p>ST_Intersects</p><p>Retourne true si deux géométries se croisent, et false dans le cas contraire.</p><p>ST_DISJOINT</p><p>ST_Disjoint</p><p>Retourne true si deux géométries ne se croisent pas, et false dans le cas contraire. L'inverse de ST_INTERSECTS.</p><p>ST_CONTAINS</p><p>ST_Contains</p><p>Retourne true si une géométrie en contient une autre, et false sinon.</p><p>ST_WITHIN</p><p>ST_Within</p><p>Retourne true si une géométrie est à l'intérieur d'une autre, et false dans le cas contraire. L'inverse de ST_CONTAINS.</p><p>Ces fonctions se comportent de manière similaire à leurs homologues PostGIS et sont utilisées de la même manière. Par exemple, <code>ST_INTERSECTS</code> renvoie un message vrai si deux géométries se croisent et un message faux dans le cas contraire. Si vous suivez les liens de documentation dans le tableau ci-dessus, vous remarquerez que tous les exemples ES|QL se trouvent dans une clause <code>WHERE</code> après une clause <code>FROM</code>, alors que tous les exemples PostGIS utilisent des géométries littérales. En fait, les deux plates-formes permettent d'utiliser les fonctions dans n'importe quelle partie de la requête où elles sont utiles.</p><p>Le premier exemple dans la documentation PostGIS pour <code>ST_INTERSECTS</code> est le suivant :</p>SELECT ST_Intersects(
    'POINT(0 0)'::geometry,
    'LINESTRING ( 2 0, 0 2 )'::geometry
);
<p>L'équivalent en ES|QL serait le suivant :</p>ROW ST_INTERSECTS(
    "POINT(0 0)"::geo_point,
    "LINESTRING ( 2 0, 0 2 )"::geo_shape
)
<p>Notez que nous n'avons pas spécifié le SRID dans l'exemple de PostGIS. En effet, dans PostGIS, lorsque l'on utilise le type <code>geometry</code>, tous les calculs sont effectués sur un système de coordonnées planaires et, par conséquent, si les deux géométries ont le même SRID, le SRID n'a pas d'importance. Dans Elasticsearch, c'est également le cas pour la plupart des fonctions, mais il existe des exceptions où <code>geo_shape</code> et <code>geo_point</code> utilisent des calculs sphériques, comme nous le verrons dans le prochain blog sur la recherche de distance spatiale.</p><h2>ES|QL polyvalence</h2><p>Nous avons donc vu ci-dessus des exemples d'utilisation de fonctions spatiales dans les clauses <code>WHERE</code> et dans les commandes <code>ROW</code>. Où cela aurait-il un sens ? Un endroit très utile est la commande <code>EVAL</code>. Cette commande permet d'évaluer une expression et de renvoyer le résultat. Par exemple, déterminons si les centroïdes de tous les aéroports regroupés par nom de pays se trouvent à l'intérieur d'une frontière délimitant le pays :</p>FROM airports
| EVAL in_uk = ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))"))
| EVAL in_iceland = ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON ((-25.4883 65.5312, -23.4668 66.7746, -18.4131 67.4749, -13.0957 66.2669, -12.3926 64.4159, -20.1270 62.7346, -24.7852 63.3718, -25.4883 65.5312))"))
| EVAL within_uk = ST_WITHIN(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))"))
| EVAL within_iceland = ST_WITHIN(location, TO_GEOSHAPE("POLYGON ((-25.4883 65.5312, -23.4668 66.7746, -18.4131 67.4749, -13.0957 66.2669, -12.3926 64.4159, -20.1270 62.7346, -24.7852 63.3718, -25.4883 65.5312))"))
| STATS centroid = ST_CENTROID_AGG(location), count=COUNT() BY in_uk, in_iceland, within_uk, within_iceland
| SORT count ASC
<p>Les résultats sont attendus, les centroïdes des aéroports britanniques sont situés à l'intérieur de la frontière britannique, mais pas à l'intérieur de la frontière islandaise, et vice versa :</p><p>centroïde</p><p>Compte</p><p>in_uk</p><p>en_pays</p><p>within_uk</p><p>à l'intérieur de la patrie</p><p>POINT (-21.946634463965893 64.13187285885215)</p><p>1</p><p>faux</p><p>vrai</p><p>faux</p><p>vrai</p><p>POINT (-2.597342072712148 54.33551226578214)</p><p>17</p><p>vrai</p><p>faux</p><p>vrai</p><p>faux</p><p>POINT (0.04453958108176276 23.74658354606057)</p><p>873</p><p>faux</p><p>faux</p><p>faux</p><p>faux</p><p>En fait, ces fonctions peuvent être utilisées dans n'importe quelle partie de la requête où leur signature a un sens. Ils prennent tous deux arguments, qui sont soit un objet spatial littéral, soit un champ d'un type spatial, et renvoient tous une valeur booléenne. Il est important de noter que le système de référence des coordonnées (CRS) des géométries doit correspondre, sinon une erreur sera renvoyée. Cela signifie que vous ne pouvez pas mélanger les types <code>geo_shape</code> et <code>cartesian_shape</code> dans le même appel de fonction. Vous pouvez toutefois mélanger les types <code>geo_point</code> et <code>geo_shape</code>, car le type <code>geo_point</code> est un cas particulier du type <code>geo_shape</code>, et tous deux partagent le même système de référence de coordonnées. La documentation relative à chacune des fonctions définies ci-dessus énumère les combinaisons de types prises en charge.</p><p>En outre, chaque argument peut être un littéral spatial ou un champ, dans l'un ou l'autre ordre. Vous pouvez même spécifier deux champs, deux littéraux, un champ et un littéral, ou un littéral et un champ. La seule condition est que les types soient compatibles. Par exemple, cette requête compare deux champs dans le même index :</p>FROM airport_city_boundaries
| EVAL in_city = ST_INTERSECTS(city_location, city_boundary)
| STATS count=COUNT(*) BY in_city
| SORT count ASC
| EVAL cardinality = CASE(count &lt; 10, "very few", count &lt; 100, "few", "many")
| KEEP cardinality, count, in_city
<p>La requête demande essentiellement si la ville est située à l'intérieur des limites de la ville, ce qui devrait généralement être le cas, mais il y a toujours des exceptions :</p><p>cardinalité</p><p>Compte</p><p>dans_la_ville</p><p>peu</p><p>29</p><p>faux</p><p>nombreux</p><p>740</p><p>vrai</p><p>Une question bien plus intéressante serait de savoir si l'emplacement de l'aéroport se trouve à l'intérieur des limites de la ville desservie par l'aéroport. Cependant, l'emplacement de l'aéroport se trouve dans un index différent de celui qui contient les limites de la ville. Il faut donc trouver une méthode pour interroger efficacement les données de ces deux index distincts et les mettre en corrélation.</p><h2>Jointures spatiales</h2><p>ES|QL ne prend pas <code>JOIN</code> en charge les commandes, mais vous pouvez réaliser un cas spécial de jointure à l'aide de la <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich"><code>ENRICH</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich"> </a>commande, qui se comporte de la même manière qu'une "jointure gauche" en SQL. Cette commande s'apparente à une "jointure gauche" en SQL, vous permettant d'enrichir les résultats d'un index avec des données d'un autre index sur la base d'une relation spatiale entre les deux ensembles de données.</p><p>Par exemple, enrichissons les résultats d'un tableau d'aéroports avec des informations supplémentaires sur la ville qu'ils desservent en trouvant la limite de la ville qui contient l'emplacement de l'aéroport, puis effectuons quelques statistiques sur les résultats :</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
| MV_EXPAND city_boundary
| EVAL boundary_wkt_length = LENGTH(TO_STRING(city_boundary))
| STATS centroid = ST_CENTROID_AGG(location), count = COUNT(city_location), min_wkt = MIN(boundary_wkt_length), max_wkt = MAX(boundary_wkt_length) BY region
| SORT count DESC
| LIMIT 5
<p>Cette méthode permet d'obtenir les 5 régions qui comptent le plus d'aéroports, ainsi que le centroïde de tous les aéroports qui ont des régions correspondantes et la longueur de la représentation WKT des limites des villes à l'intérieur de ces régions :</p><p>centroïde</p><p>Compte</p><p>min_wkt</p><p>max_wkt</p><p>région</p><p>POINT (-32.56093470960719 32.598117914802714)</p><p>90</p><p>207</p><p>207</p><p>nul</p><p>POINT (-73.94515332765877 40.70366442203522)</p><p>9</p><p>438</p><p>438</p><p>Ville de New York</p><p>POINT (-83.10398317873478 42.300230911932886)</p><p>9</p><p>473</p><p>473</p><p>Détroit</p><p>POINT (-156.3020245861262 20.176383580081165)</p><p>5</p><p>307</p><p>803</p><p>Hawaï</p><p>POINT (-73.88902732171118 45.57078813901171)</p><p>4</p><p>837</p><p>837</p><p>Montréal</p><p>Alors, que s'est-il vraiment passé ? Où s'est produite la supposée <code>JOIN</code>? L'essentiel de la question réside dans la commande <code>ENRICH</code>:</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
<p>Cette commande demande à Elasticsearch d'enrichir les résultats extraits de l'index <code>airports</code> et d'effectuer une jointure <code>intersects</code> entre le champ <code>city_location</code> de l'index original et le champ <code>city_boundary</code> de l'index <code>airport_city_boundaries</code>, que nous avons utilisé dans quelques exemples plus tôt. Mais certaines de ces informations ne sont pas clairement visibles dans cette requête. Ce que nous voyons, c'est le nom d'une politique d'enrichissement <code>city_boundaries</code>, et l'information manquante est encapsulée dans cette définition de politique.</p>{
  "geo_match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}
<p>Ici, nous pouvons voir qu'il effectuera une requête <code>geo_match</code> (<code>intersects</code> est la valeur par défaut), que le champ à comparer est <code>city_boundary</code> et que les champs <code>enrich_fields</code> sont les champs que nous voulons ajouter au document d'origine. L'un de ces champs, le <code>region</code>, a été utilisé comme clé de regroupement pour la commande <code>STATS</code>, ce que nous n'aurions pas pu faire sans cette capacité de "jointure à gauche". Pour plus d'informations sur les politiques d'enrichissement, voir la <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-setup.html">documentation d'enrichissement</a>. En lisant ces documents, vous remarquerez qu'ils décrivent l'utilisation des index d'enrichissement pour enrichir les données au moment de l'indexation, en configurant les pipelines d'ingestion. Cela n'est pas nécessaire pour ES|QL, car la commande <code>ENRICH</code> fonctionne au moment de la requête. Il suffit de préparer l'index d'enrichissement avec les données et la politique d'enrichissement nécessaires, puis d'utiliser la commande <code>ENRICH</code> dans vos requêtes ES|QL.</p><p>Vous pouvez également remarquer que la région la plus fréquemment trouvée est <code>null</code>. Qu'est-ce que cela peut signifier ? Rappelez-vous que j'ai comparé cette commande à une "jointure gauche" en SQL, ce qui signifie que si aucune limite de ville correspondante n'est trouvée pour un aéroport, l'aéroport est toujours renvoyé, mais avec les valeurs <code>null</code> pour les champs de l'index <code>airport_city_boundaries</code>. Il s'avère que 89 aéroports n'ont pas trouvé de correspondance avec <code>city_boundary</code>, et un aéroport avec une correspondance où le champ <code>region</code> était <code>null</code>. Cela a conduit à un décompte de 90 aéroports sans <code>region</code> dans les résultats. Un autre détail intéressant est la nécessité de la commande <code>MV_EXPAND</code>. Cela est nécessaire car la commande <code>ENRICH</code> peut renvoyer plusieurs résultats pour chaque ligne d'entrée, et <code>MV_EXPAND</code> permet de séparer ces résultats en plusieurs lignes, une pour chaque résultat. Cela explique également pourquoi "Hawaii" affiche des résultats différents de <code>min_wkt</code> et <code>max_wkt</code>: il y avait plusieurs régions portant le même nom mais ayant des limites différentes.</p><h2>Cartes Kibana</h2><p>Kibana a ajouté la prise en charge de Spatial ES|QL dans l'application Maps. Cela signifie que vous pouvez désormais utiliser ES|QL pour rechercher des données géospatiales dans Elasticsearch et visualiser les résultats sur une carte.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91922eb4ef43d290/6a16f7161949f737bfe7a7b5/bd78470bd8a4bc60f0db7006bd804b8fe87e2fea-1440x683.png" alt="Couches Kibana ES|QL" /><p>Il existe une nouvelle option de couche dans le menu d'ajout de couches, appelée "ES|QL". Comme toutes les fonctions géospatiales décrites jusqu'à présent, il s'agit d'un aperçu technique "" . Cette option permet d'ajouter une couche à la carte en fonction des résultats d'une requête ES|QL. Par exemple, vous pouvez ajouter une couche à la carte qui montre tous les aéroports du monde.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5185ef7461d7e81d/6a16f718839dfa1559dcfcb1/1dd28d3d0509f92d26b0bb5320a2925f7a54c5d9-1440x736.png" alt="Kibana ES|QL - Aéroports" /><p>Vous pouvez également ajouter une couche qui montre les polygones de l'index <code>airport_city_boundaries</code> ou, mieux encore, la requête complexe <code>ENRICH</code> ci-dessus qui génère des statistiques sur le nombre d'aéroports dans chaque région.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ee3543bb811d98/6a16f71a8b73cbbe63189df1/679a0a401faa613c7cedddd07c64f614ac2b7144-1440x727.png" alt="Kibana ES|QL - Statistiques par région" /><h2>Et ensuite ?</h2><p>Vous avez peut-être remarqué que dans deux des exemples ci-dessus, nous avons inséré une autre fonction spatiale <code>ST_CENTROID_AGG</code>. Il s'agit d'une fonction d'agrégation utilisée dans la commande <code>STATS</code> et de la première des nombreuses fonctions d'analyse spatiale que nous prévoyons d'ajouter à ES|QL. Nous en parlerons sur notre blog lorsque nous en aurons plus à montrer !</p><p>Avant cela, nous souhaitons vous parler d'une fonctionnalité particulièrement intéressante sur laquelle nous avons travaillé : la possibilité d'effectuer des recherches spatiales par distance, l'une des fonctionnalités de recherche spatiale les plus utilisées d'Elasticsearch. Pouvez-vous imaginer à quoi pourrait ressembler la syntaxe des recherches à distance ? Peut-être similaire à une fonction de l'OGC ? Restez à l'écoute du prochain blog de cette série pour le découvrir !</p><p>Alerte au spoiler : Elasticsearch 8.15 vient d'être publié, et la recherche de distance spatiale avec ES|QL est incluse !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one</guid>
    <category><![CDATA[Python]]></category>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Craig Taverner]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd05627be20e89dfb/6a17d7c6414c640256944fdb/de886289dcb56494920875303b622b030b9b810f-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 12 Aug 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[De ES|QL aux objets PHP]]></title>
    <description><![CDATA[Apprenez à exécuter et à gérer les requêtes ES|QL en PHP. Suivez ce guide pour mapper les résultats ES|QL vers un objet PHP ou une classe personnalisée.]]></description>
    <content:encoded><![CDATA[<p>À partir d'elasticsearch-php <a href="https://github.com/elastic/elasticsearch-php/releases/tag/v8.13.0">v8.13.0</a>, il est possible d'exécuter des requêtes <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html">ES|QL</a> et de mapper le résultat à un objet PHP de <a href="https://www.php.net/manual/en/class.stdclass.php">stdClass</a> ou d'une classe personnalisée.</p><h2>ES|QL</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html">ES|QL</a> est un nouveau langage de requête Elasticsearch introduit dans Elasticsearch 8.11.0. Pour l'instant, il est disponible en aperçu technique. Il offre un moyen puissant de filtrer, de transformer et d'analyser les données stockées dans Elasticsearch.</p><p>Il utilise les tuyaux "" (<code>|</code>) pour manipuler et transformer les données étape par étape. Cette approche permet aux utilisateurs de composer une série d'opérations, où la sortie d'une opération devient l'entrée de la suivante, ce qui permet des transformations et des analyses de données complexes.</p><p>Par exemple, la requête suivante renvoie les 3 premiers documents (lignes) de l'index <code>sample_data</code>:</p>FROM sample_data
| LIMIT 3
<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8b0310cb335872b7/6a17d7eab1e113258679f0df/c23aee777bacdf90c63b717fd9458207dfc0511d-864x284.png" alt="ES|QL produit des tableaux" /><h2>Cas d'utilisation : Fonctionnalités ES|QL dans le client PHP officiel</h2><p>Pour illustrer les fonctionnalités ES|QL développées dans le client PHP officiel, nous avons stocké dans Elasticsearch un <a href="https://github.com/elastic/elasticsearch-php-examples/blob/main/examples/ESQL/data/books.csv">fichier CSV</a> de 81 828 livres (54,4 Mo) contenant les informations suivantes :</p>Title;Descrition;Author;Year;Publisher;Ratings
<p>Nous avons extrait cette liste de l' ensemble de <a href="https://www.kaggle.com/datasets/mohamedbakhet/amazon-books-reviews">données publiques Amazon Books Reviews.</a></p><p>Nous avons créé un index <code>books</code> avec les mappings Elasticsearch suivants :</p>'mappings' : {
    'properties': {
        'title': {
            'type': 'text'
        },
        'description': {
            'type': 'text'
        },
        'author': {
            'type': 'text'
        },
        'year': {
            'type': 'short'
        },
        'publisher': {
            'type': 'keyword'
        },
        'rating': {
            'type': 'half_float'
        }
    }
}
<p>La valeur <code>rating</code> est la moyenne des avis de classement tirés du fichier <a href="https://www.kaggle.com/datasets/mohamedbakhet/amazon-books-reviews?select=Books_rating.csv">Books_rating.csv</a> de 2,9 Go.</p><p>Vous trouverez <a href="https://github.com/elastic/elasticsearch-php-examples/blob/main/examples/ESQL/bulk.php">ici</a> le script PHP que nous avons utilisé pour importer en masse tous les livres dans Elasticsearch. L'opération en bloc a pris 7 secondes et 28 Mo de RAM en utilisant PHP 8.2.17. Avec le mappage proposé, la taille de l'index dans Elasticsearch est d'environ 62 Mo.</p><h2>Mapper les résultats ES|QL vers un objet PHP ou une classe personnalisée</h2><p>Nous pouvons exécuter une requête ES|QL en PHP en utilisant le point de terminaison <code>esql()-&gt;query()</code>. Le résultat de cette requête est une structure de données sous forme de tableau. Ceci est exprimé en JSON à l'aide des champs <code>columns</code> et <code>values</code>. Dans le champ <code>columns</code>, nous avons les définitions <code>name</code> et <code>type</code>.</p><p>Voici un exemple de requête ES|QL permettant d'obtenir les 10 meilleurs livres écrits par Stephen King, classés par ordre d'appréciation des utilisateurs :</p>$query = &lt;&lt;&lt;EOD
    FROM books
    | WHERE author == "Stephen King"
    | SORT rating DESC
    | LIMIT 10
EOD;

$result = $client-&gt;esql()-&gt;query([
    'body' =&gt; ['query' =&gt; $query]
]);
<p>Le résultat JSON d'Elasticsearch se présente comme suit :</p>{
    "columns": [
        { "name": "author", "type": "text" },
        { "name": "description", "type": "text" },
        { "name": "publisher", "type": "keyword" },
        { "name": "rating", "type": "double" },
        { "name": "title", "type": "text" },
        { "name": "year", "type": "integer" }
    ],
    "values": [
        [
            "Stephen King",
            "The author ...",
            "Turtleback",
            5.0,
            "How writers write",
            2002
        ],
        [
            "Stephen King",
            "In Blockade Billy, a retired coach...",
            "Simon and Schuster",
            5.0,
            "Blockade",
            2010
        ],
        [
            "Stephen King",
            "A chilling collection of twenty horror stories.",
            "Signet Book",
            4.55859375,
            "Night Shift (Signet)",
            1979
        ],
        ...
    ]
}
<p>Dans cet exemple, nous avons 6 propriétés (auteur, description, éditeur, note, titre, année) liées à un livre et 10 résultats, tous des livres de Stephen King.</p><p>Une liste de tous les types pris en charge dans ES|QL est présentée <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-limitations.html#esql-supported-types">ici.</a></p><p>L'objet de réponse <code>$result</code> est accessible sous la forme d'un tableau, d'une chaîne de caractères ou d'un objet (voir <a href="https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/connecting.html#client-usage">ici</a> pour plus d'informations).</p><p>L'interface objet permet d'accéder aux valeurs à l'aide de propriétés et d'index. Par exemple, <code>$result-&gt;values[0][4]</code> renvoie le titre (4) du premier livre (0) de la liste, <code>$result-&gt;values[1][3]</code> renvoie le rang (3) du deuxième livre (1), etc. Rappelez-vous que l'index d'un tableau en PHP commence à zéro.</p><p>Cette interface peut être suffisante pour certains cas d'utilisation, mais la plupart du temps, nous aimerions avoir un tableau d'objets comme résultat.</p><p>Pour convertir le résultat en un tableau d'objets, nous pouvons utiliser la nouvelle fonction <a href="https://github.com/elastic/elasticsearch-php/issues/1398">mapTo()</a> d'elasticsearch-php.</p><p>Cette fonction est disponible directement dans l'<a href="https://github.com/elastic/elasticsearch-php/blob/main/src/Response/Elasticsearch.php">objet de réponse Elasticsearch</a>. Cela signifie que vous pouvez y accéder de la manière suivante :</p>$books = $result-&gt;mapTo(); // Array of stdClass
foreach ($books as $book) {
    printf(
        "%s, %s, %d, Rating: %.2f\n",
        $book-&gt;author,
        $book-&gt;title,
        $book-&gt;year,
        $book-&gt;rating
    );
}
<p>Si vous disposez d'une classe de livre personnalisée, vous pouvez mapper le résultat en l'utilisant, comme suit :</p>class Book
{
    public string $author;
    public string $title;
    public string $description;
    public int $year;
    public float $rating;
}

$books = $result-&gt;mapTo(Book::class); // Array of Book
<p>Si votre classe possède d'autres propriétés en plus de celles incluses dans le résultat ES|QL, cela fonctionnera également. La fonction <code>mapTo()</code> n'utilisera que les propriétés renvoyées sous forme de colonnes dans le résultat ES|QL.</p><p>Vous pouvez télécharger tous les exemples présentés dans cet article <a href="https://github.com/elastic/elasticsearch-php-examples/tree/main/examples/ESQL">ici.</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-php-map-object-class</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-php-map-object-class</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[PHP]]></category>
    <dc:creator><![CDATA[Enrico Zimuel]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt99f5ab85c0713977/6a17d7ebfbc5f8072b491918/aea56270f48cb64130d1b515b983434e0960dc2f-500x500.png" length="0" type="image/png"/>
    <pubDate>Mon, 08 Apr 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>