<?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[Ruby - 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[Ruby - 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/ruby-programming</link>
    </image>
    <link>https://www.elastic.co/fr/search-labs/blog/category/ruby-programming</link>
    <atom:link href="https://www.elastic.co/fr/search-labs/rss/category/ruby-programming.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[fr]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 21:06:09 GMT</lastBuildDate>
  <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[Scripting Ruby dans Logstash]]></title>
    <description><![CDATA[Découvrez le plugin Logstash Ruby filter pour une transformation avancée des données dans votre pipeline Logstash.]]></description>
    <content:encoded><![CDATA[<p>Logstash est un pipeline de traitement de données qui ingère des données provenant de sources multiples, les transforme et les envoie vers les destinations de votre choix. Les plugins de filtrage sont essentiels pour ce processus ; ils effectuent des opérations spécifiques sur vos données lorsqu'elles passent par le pipeline.</p><p>Logstash comprend plusieurs filtres intégrés pour les tâches courantes telles que l'analyse, l'enrichissement et la modification des données. Mais parfois, vous rencontrerez des scénarios qui nécessiteront une logique personnalisée allant au-delà de ce que ces filtres standard peuvent fournir. C'est là qu'intervient le <a href="https://www.elastic.co/docs/reference/logstash/plugins/plugins-filters-ruby">plugin Ruby filter</a>.</p><p><strong>Le plugin Ruby filter vous permet d'exécuter du code Ruby personnalisé directement dans votre pipeline Logstash.</strong> Lorsque les filtres standard ne suffisent pas, le filtre Ruby vous permet de gérer des transformations de données complexes, de mettre en œuvre une logique commerciale personnalisée ou d'intégrer des systèmes externes.</p><p>Dans ce blog, nous allons explorer comment utiliser les filtres Ruby, de l'utilisation basique à l'utilisation avancée.</p><h2>Quand utiliser le filtre Ruby ?</h2><p>En tant qu'architecte consultant d'Elastic, je vois souvent des clients utiliser Logstash pour le pipeline de traitement des données, même s'il ne s'agit pas aujourd'hui d'un moteur de traitement des données à la pointe de la technologie. Ils se heurtent souvent aux limites des filtres standard lorsqu'il s'agit de manipuler des données complexes ou d'appliquer une logique personnalisée. Dans ce cas, le filtre Ruby peut aider à surmonter ces difficultés.</p><p>Le filtre Ruby est utile lorsque les filtres standard de Logstash ne peuvent pas répondre à vos besoins spécifiques. Voici quelques cas d'utilisation courants :</p><ul><li><p><strong>Manipulation de données imbriquées en profondeur</strong>: Modifier des structures JSON complexes, des tableaux dans des tableaux, ou restructurer dynamiquement des données en fonction de leur contenu.</p></li><li><p><strong>Traitement avancé des chaînes de caractères</strong>: Analyse et extraction de données structurées à partir de textes non structurés</p></li><li><p><strong>Mise en œuvre d'une logique d'entreprise complexe</strong>: Créer des transformations personnalisées qui nécessitent une logique conditionnelle, des boucles ou des calculs complexes.</p></li></ul><h2>Utilisation de base</h2><p>Commençons par un exemple simple pour comprendre le fonctionnement du filtre Ruby.</p><h3>Configuration du filtre Ruby</h3><p>Lorsque vous créez un pipeline Logstash, vous devez placer le fichier de configuration dans le répertoire <code>/etc/logstash/conf.d</code>. Alternativement, vous pouvez utiliser l'option <code>-f</code> pour spécifier le chemin vers le fichier de configuration lorsque vous démarrez Logstash manuellement, afin que vous puissiez expérimenter vos pipelines facilement.</p>$ ./bin/logstash -f /path/to/your_pipeline.conf<p>Le fichier de configuration doit avoir une extension <code>.conf</code>.</p><p>Pour utiliser le filtre Ruby, définissez un filtre <code>ruby</code> dans la section filter de votre fichier de configuration du pipeline Logstash (*.conf). Voici un exemple de base :</p>filter {
  ruby {
    code =&gt; "
      event.set('new_field', 'Hello from Ruby!')
    "
  }
}<p>Ce filtre Ruby en ligne définit une instance de filtre Ruby dans votre configuration Logstash. Le paramètre <code>code</code> fournit le script Ruby en ligne que Logstash exécutera pour chaque événement traité par ce filtre. Dans ce script, il existe une variable <code>event</code> qui représente l'événement lui-même. L'objet événement contient les données originales envoyées à Logstash et tous les champs supplémentaires créés lors des étapes de filtrage de Logstash. Vous pouvez accéder à ces champs via l'API Logstash Event telle que <code>event.get()</code> et <code>event.set()</code>. Dans cet exemple de code, <code>event.set('new_field', 'Hello from Ruby!')</code> attribue à un nouveau champ nommé <code>new_field</code> la valeur de chaîne <code>Hello from Ruby!</code>. Vous pouvez ajouter tout autre code dans ce bloc <code>code</code> si nécessaire.</p><p>Notez que cet objet <code>event</code> n'est pas un objet de hachage Ruby habituel, bien qu'il agisse comme un conteneur de données de type clé-valeur. Consultez <a href="https://www.elastic.co/docs/reference/logstash/event-api">la documentation officielle</a> pour en savoir plus sur l'API des événements.</p><h3>Externaliser le script Ruby</h3><p>Pour les transformations simples, le code Ruby en ligne est pratique. Mais pour une logique complexe ou des fonctions réutilisables, il est recommandé de déplacer le code dans un script Ruby externe. Cela permet d'améliorer la maintenabilité et de conserver une configuration propre du pipeline Logstash.</p><p>Tout d'abord, créez un script Ruby et enregistrez-le sous <code>my_ruby_script.rb</code>. Le script doit définir une méthode <code>filter</code> qui traite l'événement. Elle prend en argument un objet événement qui représente l'événement en cours de traitement. La méthode <code>filter</code> doit renvoyer un tableau d'événements à émettre. Pour supprimer l'événement, renvoyer un tableau vide.</p><p>Par exemple, le script suivant lit la rubrique <code>message</code>, calcule sa longueur et stocke le résultat dans une nouvelle rubrique appelée <code>message_length</code>.</p>def register(params)
  # This method is called when the plugin is loaded.
  # You can use it to initialize any instance variables or perform setup tasks.
end

def filter(event)
  message = event.get('message')

  if message
    event.set('message_length', message.length)
  end

  return [event]
end<p>Ensuite, définissez la configuration du filtre Ruby pour qu'il fasse référence au script à l'aide de l'option <code>path</code>. Cela indique à Logstash de charger et d'exécuter le script externe. Lors de l'utilisation de scripts externes, assurez-vous que le fichier existe et que les autorisations sont correctes.</p>filter {
  ruby {
    path =&gt; "/path/to/my_ruby_script.rb"
  }
}<p>Maintenant, chaque événement est transmis à la méthode <code>filter</code> dans <code>my_ruby_script.rb</code> et est traité par elle.</p><p>Cette approche vous permet de gérer plus efficacement une logique complexe, ce qui facilite les tests, le débogage et la réutilisation de votre code Ruby.</p><h2>Utilisation avancée</h2><p>Dans cette section, nous allons explorer quelques exemples avancés d'utilisation du filtre Ruby dans Logstash. Ces exemples montrent comment effectuer des transformations de données, enrichir des événements et mettre en œuvre une logique personnalisée à l'aide de Ruby.</p><h3>Manipulation de structures de données imbriquées</h3><p>Un événement Logstash est la structure de données centrale que Logstash traite. Il peut contenir différents champs, y compris des structures de données imbriquées telles que des tableaux et des hachages. Le filtre Ruby permet de manipuler facilement ces structures imbriquées.</p><p>Le filtre Ruby peut gérer des structures de données imbriquées, telles que des hachages et des tableaux, ce qui permet de modifier ou d'ajouter des champs dans ces structures. Cette fonction est utile lorsqu'il s'agit de traiter des formats de données complexes tels que JSON.</p>input {
  generator {
    lines =&gt; [
      '{"nested": {"key1": "value1", "key2": "value2"}}'
    ]
    count =&gt; 1
    codec =&gt; "json"
    ecs_compatibility =&gt; "disabled"
  }
}

filter {
  ruby {
    code =&gt; "
      nested_data = event.get('nested')

      if nested_data.is_a?(Hash)
        nested_data['key3'] = 'value3'
        event.set('nested', nested_data)
      end
    "
  }
}

output {
  stdout { codec =&gt; rubydebug }
}<p>Cet exemple inclut un objet JSON imbriqué dans les données d'entrée. Le filtre Ruby modifie les données imbriquées en ajoutant une nouvelle paire clé-valeur. Ce type de manipulation des données imbriquées n'est pas possible avec les filtres Logstash standard, ce qui fait du filtre Ruby une option pratique pour les structures de données complexes.</p><h3>Diviser un événement unique en plusieurs événements</h3><p>Les filtres Ruby peuvent également être utilisés pour diviser un événement unique en plusieurs événements. Ceci est utile lorsque vous avez un événement unique contenant un tableau d'éléments et que vous souhaitez créer des événements distincts pour chaque élément.</p><p>Notez que ni le pipeline d'acquisition d'Elasticsearch ni les processeurs de Beats/Elastic Agent ne prennent en charge le fractionnement des événements. C'est l'un des cas d'utilisation les plus importants pour Logstash.</p><h4>Avec filtre divisé</h4><p>Vous pouvez utiliser le filtre <code>split</code> pour diviser un événement en plusieurs événements sur la base d'un champ spécifié. Toutefois, si vous devez effectuer des transformations ou des opérations logiques supplémentaires pendant le fractionnement, vous pouvez utiliser le filtre Ruby en combinaison avec le filtre de fractionnement.</p><p>Dans l'exemple suivant, nous avons un flux RSS sous la forme d'une seule ligne de texte XML. Il contient plusieurs éléments <code>&lt;item&gt;</code>. Le filtre Ruby est utilisé pour extraire les éléments <code>&lt;item&gt;</code> du XML et les stocker dans un nouveau champ appelé <code>items</code>. Le filtre de division est ensuite utilisé pour diviser l'événement en plusieurs événements sur la base du champ <code>items</code>.</p>input {
  generator {
    lines =&gt; [
      '&lt;rss version="2.0"&gt;&lt;channel&gt;&lt;title&gt;Sample RSS&lt;/title&gt;&lt;item&gt;&lt;title&gt;Article 1&lt;/title&gt;&lt;link&gt;http://example.com/1&lt;/link&gt;&lt;description&gt;Desc 1&lt;/description&gt;&lt;/item&gt;&lt;item&gt;&lt;title&gt;Article 2&lt;/title&gt;&lt;link&gt;http://example.com/2&lt;/link&gt;&lt;description&gt;Desc 2&lt;/description&gt;&lt;/item&gt;&lt;/channel&gt;&lt;/rss&gt;'
    ]
    count =&gt; 1
    codec =&gt; "plain"
    ecs_compatibility =&gt; "disabled"
  }
}

filter {
  xml {
    source =&gt; "message"
    target =&gt; "rss"
    store_xml =&gt; true
    force_array =&gt; false
  }
  ruby {
    code =&gt; "event.set('items', event.get('[rss][channel][item]')) if event.get('[rss][channel][item]')"
  }
  split {
    field =&gt; "items"
  }
  ruby {
    code =&gt; "
      item = event.get('items')
      event.set('title', item['title']) if item['title']
      event.set('link', item['link']) if item['link']
      event.set('description', item['description']) if item['description']
    "
  }
  mutate {
    remove_field =&gt; ["@timestamp", "@version", "sequence", "host", "event", "message", "rss", "items"]
  }
}

output {
  stdout { codec =&gt; rubydebug }
}<p>Le résultat sera le suivant :</p>{
          "title" =&gt; "Article 1",
           "link" =&gt; "http://example.com/1",
    "description" =&gt; "Desc 1"
}
{
          "title" =&gt; "Article 2",
           "link" =&gt; "http://example.com/2",
    "description" =&gt; "Desc 2"
}<p>Comme vous l'avez peut-être remarqué, le filtre <code>ruby</code> n'est pas indispensable dans ce cas. Le filtre <code>split</code> peut être utilisé pour diviser l'événement en plusieurs événements sur la base du champ <code>items</code>, et le filtre <code>mutate</code> peut être utilisé pour supprimer les champs inutiles. Toutefois, si vous devez effectuer des transformations ou des opérations logiques supplémentaires pendant le fractionnement, vous pouvez utiliser le filtre Ruby.</p><h4>Utiliser un script Ruby en ligne</h4><p>Vous pouvez également utiliser un script Ruby en ligne pour diviser un événement unique en plusieurs événements en utilisant la méthode <code>event.clone</code> et la méthode <code>new_event_block variable</code>, telle que <code>new_event_block.call(new_event)</code>. Cela vous permet de créer de nouveaux événements basés sur l'événement original tout en préservant ses données.</p><p>Voici un exemple d'utilisation du filtre Ruby pour diviser un événement unique en plusieurs événements. L'entrée et la sortie sont les mêmes que dans l'exemple précédent.</p>filter {
  xml {
    source =&gt; "message"
    target =&gt; "rss"
    store_xml =&gt; true
    force_array =&gt; false
  }
  ruby {
    code =&gt; "
      items = event.get('[rss][channel][item]')
      if items.is_a?(Array)
        items.each do |item|
          new_event = event.clone
          new_event.set('title', item['title'])
          new_event.set('link', item['link'])
          new_event.set('description', item['description'])
          new_event_block.call new_event
        end
        event.cancel
      elsif items.is_a?(Hash)
        event.set('title', items['title'])
        event.set('link', items['link'])
        event.set('description', items['description'])
      end
    "
  }
  mutate {
    remove_field =&gt; ["@timestamp", "@version", "sequence", "host", "event", "message", "rss", "items"]
  }
}<h4>Utiliser un script Ruby externe</h4><p>Vous pouvez également utiliser un script Ruby externe pour diviser un événement unique en plusieurs événements.</p><p>Fichier de configuration :</p>filter {
  xml {
    source =&gt; "message"
    target =&gt; "rss"
    store_xml =&gt; true
    force_array =&gt; false
  }
  ruby {
    path =&gt; "path/to/ruby/split_event.rb"
  }
  mutate {
    remove_field =&gt; ["@timestamp", "@version", "sequence", "host", "event", "message", "rss", "items"]
  }
}<p>Le script Ruby doit être externalisé en tant que <code>split_event.rb</code>:</p>def filter(event)
  items = event.get('[rss][channel][item]')
  events = []
  if items.is_a?(Array)
    items.each do |item|
      new_event = event.clone
      new_event.set('title', item['title'])
      new_event.set('link', item['link'])
      new_event.set('description', item['description'])
      events &lt;&lt; new_event
    end
    return events
  elsif items.is_a?(Hash)
    event.set('title', items['title'])
    event.set('link', items['link'])
    event.set('description', items['description'])
    return [event]
  else
    return []
  end
end<p>N'oubliez pas que la méthode <code>filter</code> doit renvoyer un tableau d'événements. Vous pouvez renvoyer plusieurs événements en clonant un objet événement entrant et en l'ajoutant au tableau, ou vous pouvez renvoyer un seul événement sous la forme d'un tableau à un seul élément.</p>return events
# or
# return [event]<p>Cela vous permet de diviser un événement unique en plusieurs événements.</p><h3>Exécuter des commandes externes et analyser leurs résultats</h3><p>Le plugin Logstash exec input vous permet d'exécuter des commandes externes et leur sortie sera un événement de Logstash. La sortie de la commande sera stockée dans le champ <code>message</code> de l'événement.</p><p>Habituellement, la sortie des commandes système est lisible par l'homme, mais n'est pas structurée en JSON ou dans d'autres formats que Logstash peut facilement analyser. Pour ce faire, vous pouvez utiliser le filtre Ruby pour analyser la sortie et en extraire les informations.</p><p>Voici un exemple d'utilisation du plugin d'entrée <code>exec</code> pour exécuter la commande <code>ps -ef</code>, qui répertorie tous les processus en cours d'exécution sur un système de type Unix. La sortie sera analysée par le filtre Ruby afin d'extraire les informations pertinentes sur chaque processus.</p>input {
  exec {
    command =&gt; "ps -ef"
    interval =&gt; 60
  }
}

filter {
  ruby {
    code =&gt; '
      processes = []
      lines = event.get("message").split("\n")  
      lines.each_with_index do |line, index|
        # Skip header line and empty lines
        next if index == 0 || line.strip.empty?
        entry = nil
        
        # Use regex to match the ps -ef output format more flexibly
        # This pattern accounts for variable spacing and different time formats
        if line =~ /^\s*(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+([\d:]+\.?\d*)\s+(.+)$/
          uid, pid, ppid, c, stime, tty, time, cmd = $1, $2, $3, $4, $5, $6, $7, $8
          
          entry = {
            "UID" =&gt; uid,
            "PID" =&gt; pid,
            "PPID" =&gt; ppid,
            "C" =&gt; c,
            "STIME" =&gt; stime,
            "TTY" =&gt; tty,
            "TIME" =&gt; time,
            "CMD" =&gt; cmd.strip
          }
        elsif line =~ /^\s*(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(.+)$/
          # Fallback pattern for lines that might not match the exact format
          # Split the remaining part more carefully
          uid, pid, ppid, c, remainder = $1, $2, $3, $4, $5
          
          # Split remainder into STIME, TTY, TIME, CMD
          parts = remainder.strip.split(/\s+/, 4)
          if parts.length &gt;= 4
            stime, tty, time, cmd = parts[0], parts[1], parts[2], parts[3]
            
            entry = {
              "UID" =&gt; uid,
              "PID" =&gt; pid,
              "PPID" =&gt; ppid,
              "C" =&gt; c,
              "STIME" =&gt; stime,
              "TTY" =&gt; tty,
              "TIME" =&gt; time,
              "CMD" =&gt; cmd
            }
          end
        end
        if entry &amp;&amp; entry["UID"] == "0"
          original_line = line.strip
          entry["original_line"] = original_line if original_line.length &gt; 0
          processes.push(entry)
        end
      end
      event.set("processes", processes)
      event.remove("message")
      event.remove("event")
    '
  }
}

output {
  stdout { codec =&gt; rubydebug }
}<p>Cet exemple utilise le plugin d'entrée <code>exec</code> pour exécuter la commande <code>ps -ef</code> toutes les 60 secondes. Le filtre Ruby traite la sortie, en extrayant les champs pertinents tels que UID, PID, PPID, l'utilisation du CPU (C), l'heure de démarrage (STIME), TTY, le temps total du CPU (TIME), et la commande (CMD) exécutée. Cela fonctionne bien dans mon environnement macOS, mais il se peut que vous deviez ajuster les motifs des expressions rationnelles pour qu'ils correspondent au format de sortie de la commande <code>ps -ef</code> sur votre système.</p><h3>Utiliser les bibliothèques intégrées</h3><p>Le plugin de filtrage Ruby vous permet d'utiliser des bibliothèques Ruby intégrées, qui peuvent s'avérer très utiles pour diverses tâches. Par exemple, vous pouvez utiliser la bibliothèque <code>json</code> pour analyser les chaînes JSON ou la bibliothèque <code>date</code> pour manipuler les dates.</p><p>Voici un exemple d'utilisation de la bibliothèque <code>json</code> pour analyser une chaîne JSON stockée dans un champ :</p>require 'json'

def filter(event)
  json_string = event.get('message')
  parsed_json = JSON.parse(json_string)
  event.set('parsed_json', parsed_json)
  return [event]
end<p>Pour éviter d'avoir besoin de la bibliothèque à chaque fois, vous devriez externaliser votre code Ruby afin d'utiliser l'instruction <code>require</code> au début de votre script de filtrage Ruby. Cela chargera la bibliothèque une fois et la rendra disponible pour une utilisation dans votre script.</p><p>Pour vérifier quelles sont les bibliothèques disponibles dans votre environnement, vous pouvez dresser la liste des bibliothèques intégrées en exécutant le code suivant dans le filtre Ruby :</p>Gem.loaded_specs.sort_by { |name, _| name }.each do |name, spec|
  puts "#{name}: #{spec.version}"
end<p><strong>Note : </strong>Les bibliothèques intégrées ne sont pas officiellement supportées par Logstash, et leur comportement peut changer ou elles peuvent ne pas être disponibles dans les versions futures. Utilisez-les à vos risques et périls.</p><h2>Conclusion</h2><p>Le filtre Logstash Ruby vous permet de personnaliser et d'étendre les capacités de vos pipelines Logstash. Dans ce billet, nous avons couvert les bases de l'utilisation du filtre Ruby et fourni des exemples d'utilisation avancée.</p><p>En tirant parti du filtre Ruby, vous pouvez effectuer des tâches de traitement de données complexes qui nécessitent une logique personnalisée ou des manipulations avancées. Que vous travailliez avec des structures de données imbriquées, que vous fractionniez des événements ou que vous analysiez et convertissiez du texte complexe/non structuré en JSON structuré, le filtre Ruby offre la flexibilité nécessaire pour répondre à vos besoins spécifiques.</p><p>Nous espérons que ce guide vous a apporté les connaissances et l'inspiration nécessaires pour explorer tout le potentiel du filtre Logstash Ruby. Bonne lecture !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ruby-scripting-logstash</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ruby-scripting-logstash</guid>
    <category><![CDATA[Indexer des données]]></category>
    <category><![CDATA[Ruby]]></category>
    <dc:creator><![CDATA[Dai Sugimori]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt503d18396642e73e/6a17f62aaf47b68527cde121/b1bcd63c033ccbde102c20ba3085f165f9289a71-1600x1000.png" length="0" type="image/png"/>
    <pubDate>Tue, 24 Jun 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Comment migrer votre application Ruby d'OpenSearch vers Elasticsearch ?]]></title>
    <description><![CDATA[Un guide pour migrer une base de code Ruby du client OpenSearch vers le client Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Le client OpenSearch Ruby a été dérivé du client Elasticsearch Ruby dans la version <code>7.x</code>, les bases de code sont donc relativement similaires. Cela signifie que lors de la migration d'un code Ruby d'OpenSearch vers Elasticsearch, le code des bibliothèques clientes respectives sera très familier. Dans ce billet, je vais montrer un exemple d'application Ruby qui utilise OpenSearch et les étapes pour migrer ce code vers Elasticsearch.</p><p>Les deux clients sont publiés sous la célèbre licence Apache 2.0, ce qui en fait des logiciels libres et gratuits. La licence d'Elasticsearch a été récemment mise à jour et le cœur d'Elasticsearch et de Kibana est publié sous la licence Open Source AGPL approuvée par l'OSI depuis la version 8.16.</p><h2>Prise en compte de la version d'Elasticsearch lors de la migration d'une application Ruby</h2><p>Lors de la migration, il convient de prendre en compte la version d'Elasticsearch qui sera utilisée. Nous recommandons d'utiliser la dernière version stable, qui, au moment de la rédaction de ce document, est <code>8.17.0</code>. Les versions mineures du client Elasticsearch Ruby suivent les versions mineures d'Elasticsearch. Ainsi, pour Elasticsearch <code>8.17.x</code>, vous pouvez utiliser la version <code>8.17.x</code> de la gem Ruby.</p><p>OpenSearch a été dérivé d'Elasticsearch 7.10.2. Les API peuvent donc avoir changé et des fonctionnalités différentes peuvent être utilisées sur l'un ou l'autre. Mais cela n'entre pas dans le cadre de cet article, et je vais seulement examiner les opérations les plus courantes dans un exemple d'application.</p><p>Pour Ruby on Rails, vous pouvez utiliser le client Elasticsearch officiel ou les <a href="https://github.com/elastic/elasticsearch-rails/">bibliothèques d'intégration Rails</a>. Nous recommandons de migrer vers la dernière version stable d'Elasticsearch et du client respectivement. La version de la gem <code>elasticsearch-rails</code> <code>8.0.0</code> supporte Rails <code>6.1</code>, <code>7.0</code> et <code>7.1</code> et Elasticsearch <code>8.x</code>.</p><h2>Le code</h2><p>Pour cet exemple, j'ai suivi les étapes d'<a href="https://opensearch.org/docs/latest/install-and-configure/install-opensearch/tar/">installation d'OpenSearch à partir d'une archive.</a> Après avoir téléchargé et extrait l'archive, j'ai dû définir un mot de passe administrateur initial que j'utiliserai plus tard pour instancier le client.</p><p>J'ai créé un répertoire avec un <code>Gemfile</code> qui ressemble à ceci :</p>source 'https://rubygems.org'

gem 'opensearch-ruby'<p>Après avoir lancé <code>bundle install</code>, la gem est installée pour mon projet. Ceci a installé la version <code>3.4.0</code> de opensearch-ruby et la version d'OpenSearch que j'utilise est <code>2.18.0</code>. J'ai écrit le code dans un fichier <code>example_code.rb</code> dans le même répertoire. Le code initial de ce fichier est l'instanciation d'un client OpenSearch :</p>require 'opensearch'

client = OpenSearch::Client.new(
  host: 'https://localhost:9200',
  user: 'admin',
  password: ENV['OPENSEARCH_INITIAL_ADMIN_PASSWORD'],
  transport_options: { ssl: { verify: false } }
)<p>Le paramètre de l'option de transport <code>ssl: { verify: false}</code> est transmis conformément au guide de l'utilisateur afin de faciliter les tests. En production, cela doit être configuré en fonction du déploiement d'OpenSearch.</p><p>Depuis la version 2.12.0 d'OpenSearch, la variable d'environnement <code>OPENSEARCH_INITIAL_ADMIN_PASSWORD</code> doit être définie avec un mot de passe fort lors de l'exécution du script d'installation. En suivant les étapes d'installation d'OpenSearch à partir d'une archive, j'ai exporté la variable dans ma console et elle est maintenant disponible pour mon script Ruby.</p><p>Une API simple pour s'assurer que le client se connecte à OpenSearch consiste à utiliser l'API <code>cluster.health</code>:</p>puts 'HEALTH:'
pp client.cluster.health<p>Et en effet, cela fonctionne :</p>$ be ruby example_code.rb
HEALTH:
{"cluster_name"=&gt;"opensearch",
"status"=&gt;"yellow",
 "timed_out"=&gt;false,
 "number_of_nodes"=&gt;1,
 "number_of_data_nodes"=&gt;1,<p>J'ai testé certains des exemples courants que nous avons dans la documentation du client Elasticsearch Ruby, et ils fonctionnent comme prévu :</p>index = 'books'
puts 'Creating index'
response = client.indices.create(index: index)
puts response
# Creating index
# {"acknowledged"=&gt;true, "shards_acknowledged"=&gt;true, "index"=&gt;"books"}

puts 'Indexing a document'
document = { title: 'The Time Machine', author: 'H. G. Wells', year: 1895 }
response = client.index(index: index, body: document, refresh: true)
puts response
# Indexing document
# {"_index"=&gt;"books", "_id"=&gt;"esalT5MB4vnuJz5TtqOc", "_version"=&gt;1, "result"=&gt;"created", "forced_refresh"=&gt;true, "_shards"=&gt;{"total"=&gt;2, "successful"=&gt;1, "failed"=&gt;0}, "_seq_no"=&gt;0, "_primary_term"=&gt;1}

id = response['_id']
puts 'Getting document'
response = client.get(index: index, id: id)
puts response
# Getting document
# {"_index"=&gt;"books", "_id"=&gt;"esalT5MB4vnuJz5TtqOc", "_version"=&gt;1, "_seq_no"=&gt;0, "_primary_term"=&gt;1, "found"=&gt;true, "_source"=&gt;{"title"= &gt;"The Time Machine", "author"=&gt;"H. G. Wells", "year"=&gt;1895}}

puts "Does an index exist?"
puts client.indices.exists(index: 'imaginary_index')
# Does an index exist?
# false

puts 'Processing Bulk request'
body = [
  { index: { _index: 'books', data: { name: 'Leviathan Wakes', author: 'James S.A. Corey', release_date: '2011-06-02', page_count: 561 } } },
  { index: { _index: 'books', data: { name: 'Hyperion', author: 'Dan Simmons', release_date: '1989-05-26', page_count: 482 } } },
  { index: { _index: 'books', data: { name: 'Dune', author: 'Frank Herbert', release_date: '1965-06-01', page_count: 604 } } },
  { index: { _index: 'books', data: { name: 'Dune Messiah', author: 'Frank Herbert', release_date: '1969-10-15', page_count: 331 } } },
  { index: { _index: 'books', data: { name: 'Children of Dune', author: 'Frank Herbert', release_date: '1976-04-21', page_count: 408 } } },
  { index: { _index: 'books', data: { name: 'God Emperor of Dune', author: 'Frank Herbert', release_date: '1981-05-28', page_count: 454 } } },
  { index: { _index: 'books', data: { name: 'Consider Phlebas', author: 'Iain M. Banks', release_date: '1987-04-23', page_count: 471 } } },
  { index: { _index: 'books', data: { name: 'Pandora\'s Star', author: 'Peter F. Hamilton', release_date: '2004-03-02', page_count: 768 } } },
  { index: { _index: 'books', data: { name: 'Revelation Space', author: 'Alastair Reynolds', release_date: '2000-03-15', page_count: 585 } } },
  { index: { _index: 'books', data: { name: 'A Fire Upon the Deep', author: 'Vernor Vinge', release_date: '1992-06-01', page_count: 613 } } },
  { index: { _index: 'books', data: { name: 'Ender\'s Game', author: 'Orson Scott Card', release_date: '1985-06-01', page_count: 324 } } },
  { index: { _index: 'books', data: { name: '1984', author: 'George Orwell', release_date: '1985-06-01', page_count: 328 } } },
  { index: { _index: 'books', data: { name: 'Fahrenheit 451', author: 'Ray Bradbury', release_date: '1953-10-15', page_count: 227 } } },
  { index: { _index: 'books', data: { name: 'Brave New World', author: 'Aldous Huxley', release_date: '1932-06-01', page_count: 268 } } },
  { index: { _index: 'books', data: { name: 'Foundation', author: 'Isaac Asimov', release_date: '1951-06-01', page_count: 224 } } },
  { index: { _index: 'books', data: { name: 'The Giver', author: 'Lois Lowry', release_date: '1993-04-26', page_count: 208 } } },
  { index: { _index: 'books', data: { name: 'Slaughterhouse-Five', author: 'Kurt Vonnegut', release_date: '1969-06-01', page_count: 275 } } },
  { index: { _index: 'books', data: { name: 'The Hitchhiker\'s Guide to the Galaxy', author: 'Douglas Adams', release_date: '1979-10-12', page_count: 180 } } },
  { index: { _index: 'books', data: { name: 'Snow Crash', author: 'Neal Stephenson', release_date: '1992-06-01', page_count: 470 } } },
  { index: { _index: 'books', data: { name: 'Neuromancer', author: 'William Gibson', release_date: '1984-07-01', page_count: 271 } } },
  { index: { _index: 'books', data: { name: 'The Handmaid\'s Tale', author: 'Margaret Atwood', release_date: '1985-06-01', page_count: 311 } } },
  { index: { _index: 'books', data: { name: 'Starship Troopers', author: 'Robert A. Heinlein', release_date: '1959-12-01', page_count: 335 } } },
  { index: { _index: 'books', data: { name: 'The Left Hand of Darkness', author: 'Ursula K. Le Guin', release_date: '1969-06-01', page_count: 304 } } },
  { index: { _index: 'books', data: { name: 'The Moon is a Harsh Mistress', author: 'Robert A. Heinlein', release_date: '1966-04-01', page_count: 288 } } }
]
puts client.bulk(body: body, refresh: true)
# Processing Bulk request
# {"took"=&gt;38, "errors"=&gt;false, "items"=&gt;[{"index"=&gt;{"_index"=&gt;"books", "_id"=&gt;" ...

query = { query: { multi_match: { query: 'dune', fields: ['name'] } } }
puts 'Search results'
response = client.search(index: index, body: query)
puts response
# Search results
# {"_index"=&gt;"books", "_id"=&gt;"oEawT5MBOXHuGXdEu5Wu", "_score"=&gt;2.2886353, "_source"=&gt;{"name"=&gt;"Dune", "author"=&gt;"Frank Herbert", "release_date"=&gt;"1965-06-01", "page_count"=&gt;604}}
# {"_index"=&gt;"books", "_id"=&gt;"oUawT5MBOXHuGXdEu5Wu", "_score"=&gt;1.8893257, "_source"=&gt;{"name"=&gt;"Dune Messiah", "author"=&gt;"Frank Herbert", "release_date"=&gt;"1969-10-15", "page_count"=&gt;331}}
# {"_index"=&gt;"books", "_id"=&gt;"okawT5MBOXHuGXdEu5Wu", "_score"=&gt;1.6086557, "_source"=&gt;{"name"=&gt;"Children of Dune", "author"=&gt;"Frank Herbert", "release_date"=&gt;"1976-04-21", "page_count"=&gt;408}}
# {"_index"=&gt;"books", "_id"=&gt;"o0awT5MBOXHuGXdEu5Wu", "_score"=&gt;1.40059, "_source"=&gt;{"name"=&gt;"God Emperor of Dune", "author"=&gt;"Frank Herbert", "release_date"=&gt;"1981-05-28", "page_count"=&gt;454}}

puts 'Updating document'
document = { title: 'Walkaway', author: 'Cory Doctorow', release_date: '2017' }
response = client.index(index: index, body: document, refresh: true)
id = response['_id']
response = client.update(index: index, id: id, body: { doc: { release_date: '2017-04-26' } })
puts response
# Updating document
# {"_index"=&gt;"books", "_id"=&gt;"degnZJMBIGr4X0Yim55L", "_version"=&gt;2, "result"=&gt;"updated", "_shards"=&gt;{"total"=&gt;2, "successful"=&gt;1, "failed"=&gt;0}, "_seq_no"=&gt;26, "_primary_term"=&gt;1}

puts 'Retrieveing multiple documents'
response = client.search(index: index, body: { query: { match_all: {} }, size: 3, stored_fields: '_id' })
ids = response['hits']['hits']
ids.map { |a| a.delete('_score') }
response = client.mget(body: { docs: [{ _index: index, _id: ids }] })
puts response
# Retrieveing multiple documents
# {"docs"=&gt;[{"_index"=&gt;"books", "_id"=&gt;"qeg2ZJMBIGr4X0YiiqD2", "_version"=&gt;1, "_seq_no"=&gt;0, "_primary_term"=&gt;1, "found"=&gt;true, "_source"=&gt;{"title"=&gt;"The Time Machine", "author"=&gt;"H. G. Wells", "year"=&gt;1895}}, {"_index"=&gt;"books", "_id"=&gt;"q-g2ZJMBIGr4X0Yii6Ah", "_version"=&gt;1, "_seq_no"=&gt;1, "_primary_term"=&gt;1, "found"=&gt;true, "_source"=&gt;{"name"=&gt;"Leviathan Wakes", "author"=&gt;"James S.A. Corey", "release_date"=&gt;"2011-06-02", "page_count"=&gt;561}}, {"_index"=&gt;"books", "_id"=&gt;"rOg2ZJMBIGr4X0Yii6Ah", "_version"=&gt;1, "_seq_no"=&gt;2, "_primary_term"=&gt;1, "found"=&gt;true, "_source"=&gt;{"name"=&gt;"Hyperion", "author"=&gt;"Dan Simmons", "release_date"=&gt;"1989-05-26", "page_count"=&gt;482}}]}

puts "Count #{client.count(index: index)['count']}"
puts 'Deleting by query'
response = client.delete_by_query(index: index, body: { query: { match: { author: 'Robert A. Heinlein' } } }, refresh: true)
puts response
puts "Count #{client.count(index: index)['count']}"
# Count 26
# Deleting by query
# {"took"=&gt;16, "timed_out"=&gt;false, "total"=&gt;2, "deleted"=&gt;2, "batches"=&gt;1, "version_conflicts"=&gt;0, "noops"=&gt;0, "retries"=&gt;{"bulk"=&gt;0, "search"=&gt;0}, "throttled_millis"=&gt;0, "requests_per_second"=&gt;-1.0, "throttled_until_millis"=&gt;0, "failures"=&gt;[]}
# Count 24

puts 'Deleting document'
response = client.delete(index: index, id: id)
puts response
# Deleting document
# {"_index"=&gt;"books", "_id"=&gt;"nEawT5MBOXHuGXdEu5WA", "_version"=&gt;2, "result"=&gt;"deleted", "_shards"=&gt;{"total"=&gt;2, "successful"=&gt;1, "failed"=&gt;0}, "_seq_no"=&gt;25, "_primary_term"=&gt;1}

puts 'Deleting index'
response = client.indices.delete(index: index)
puts response
# Deleting index
# {"acknowledged"=&gt;true}<h2>Migration d'une application Ruby vers Elasticsearch</h2><p>La première étape consiste à ajouter <code>elasticsearch-ruby</code> dans le fichier Gemfile. Après l'exécution de <code>bundle install</code>, le client Elasticsearch Ruby gem sera installé. Si vous souhaitez tester votre code avant de migrer complètement, vous pouvez initialement laisser la gem <code>opensearch-ruby</code> en place.</p><p>La prochaine étape importante sera l'instanciation du client. Cela va dépendre de la manière dont vous utilisez Elasticsearch. Afin de conserver une approche similaire pour ces exemples, je suivrai les étapes de la section <a href="https://www.elastic.co/downloads/elasticsearch">Télécharger Elasticsearch</a> et l'exécuter localement.</p><p>Lors de l'exécution de <code>bin/elasticsearch</code>, Elasticsearch démarre avec des fonctions de sécurité automatiquement configurées. Veillez à copier le mot de passe de l'utilisateur élastique (mais vous pouvez le réinitialiser en lançant <code>bin/elasticsearch-reset-password -u elastic</code>). Si vous suivez cet exemple, assurez-vous d'arrêter OpenSearch avant de démarrer Elasticsearch, car ils fonctionnent sur le même port.</p><p>Au début de <code>example_code.rb</code>, j'ai commenté l'instanciation du client OpenSearch et j'ai ajouté l'instanciation d'un client Elasticsearch :</p># require 'opensearch'

# client = OpenSearch::Client.new(
#   host: 'https://localhost:9200',
#   user: 'admin',
#   password: ENV['OPENSEARCH_INITIAL_ADMIN_PASSWORD']
#   transport_options: { ssl: { verify: false } }
# )

require 'elasticsearch'

client = Elasticsearch::Client.new(
  host: 'https://localhost:9200',
  user: ENV['ELASTICSEARCH_USER'],
  password: ENV['ELASTICSEARCH_PASSWORD'],
  transport_options: { ssl: { verify: false } }
)<p>Comme vous pouvez le constater, le code est presque identique dans ce scénario de test. Elle diffère en fonction du déploiement d'Elasticsearch et de la manière dont vous décidez de vous connecter et de vous authentifier. Il en va de même pour OpenSearch en ce qui concerne la sécurité, l'option de ne pas vérifier ssl ne sert qu'à des fins de test et ne doit pas être utilisée en production.</p><p>Une fois le client configuré, j'exécute à nouveau le code avec : <code>bundle exec ruby example_code.rb</code>. Et tout fonctionne !</p><h2>Déboguer les problèmes de migration</h2><p>En fonction des API que votre application utilise, il est possible que vous receviez une erreur lorsque vous exécutez votre code contre Elasticsearch si les API d'OpenSearch divergent. La <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html">documentation sur les API REST</a> est une référence essentielle pour obtenir des informations détaillées sur l'utilisation des API. Veillez à consulter la documentation relative à la version d'Elasticsearch que vous utilisez. Vous pouvez également consulter la référence <a href="https://rubydoc.info/gems/elasticsearch-api"><code>Elasticsearch::API</code></a>.</p><p>Voici quelques exemples d'erreurs que vous pouvez rencontrer avec Elasticsearch :</p><ul><li><p><code>ArgumentError: Required argument '&lt;ARGUMENT&gt;' missing</code> - Il s'agit d'une erreur du client qui se produit lorsqu'il manque un paramètre requis dans une demande.</p></li><li><p><code>Elastic::Transport::Transport::Errors::BadRequest: [400] {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"request [/example/_doc] contains unrecognized parameter: [test]"}]...</code> Cette erreur provient d'Elasticsearch et signifie que le code client utilise un paramètre qu'Elasticsearch ne reconnaît pas pour l'API utilisée.</p></li></ul><p>Le client Elasticsearch lèvera les erreurs d'Elasticsearch avec le message d'erreur détaillé envoyé par le serveur. Ainsi, pour les paramètres ou les points de terminaison non pris en charge, l'erreur devrait vous informer de ce qui est différent.</p><h2>Conclusion</h2><p>Comme nous l'avons démontré avec cet exemple de code, la migration d'une application Ruby d'OpenSearch vers Elasticsearch n'est pas trop complexe du côté de Ruby. Vous devez être conscient des versions et des éventuelles divergences entre les API des moteurs de recherche. Mais pour les actions les plus courantes, le principal changement lors de la migration des clients se situe au niveau de l'instanciation. Ils sont tous deux similaires à cet égard, mais la façon dont l'hôte et les informations d'identification sont définis varie en fonction de la manière dont la pile est déployée. Une fois que le client est configuré et que vous avez vérifié qu'il se connecte à Elasticsearch, vous pouvez remplacer le client OpenSearch par le client Elasticsearch.
</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ruby-opensearch-elasticsearch-migration</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ruby-opensearch-elasticsearch-migration</guid>
    <category><![CDATA[Ruby]]></category>
    <dc:creator><![CDATA[Fernando Briano]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f2ce1fb5cbf7d70/6a17e1dd148009bc02b486af/47756f629737d47c4430860ea23366a8d24c90d9-1280x720.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 13 Dec 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>