在 Ruby 客户端里用 ES|QL

一、两种使用姿势概览

  1. 直接用 ES|QL API(client.esql.query)
  • 最灵活:能选择 JSON / CSV / text 等返回格式,并细调分隔符、locale 等。
  • 默认返回:{"columns":[...], "values":[...]} 的 Hash。
  1. Ruby ES|QL Helper(Elasticsearch::Helpers::ESQLHelper)
  • 把上面的原始结构映射成按列名键入的数组/哈希,更贴近业务代码。
  • 还能对列指定 Proc 做类型转换(如时间→DateTime,IP→IPAddr)。

还可以配合 elastic-esql 这个 gem 用 Ruby 风格链式构建 ES|QL 语句。

二、方式一:直接调用 ES|QL API(最灵活)

ruby 复制代码
query = <<~ESQL
  FROM sample_data
  | EVAL duration_ms = ROUND(event.duration / 1000000.0, 1)
ESQL

response = client.esql.query(body: { query: query })
puts response

默认响应结构(示意)

ruby 复制代码
{
  "columns" => [
    {"name"=>"@timestamp", "type"=>"date"},
    {"name"=>"client.ip", "type"=>"ip"},
    {"name"=>"event.duration", "type"=>"long"},
    {"name"=>"message", "type"=>"keyword"},
    {"name"=>"duration_ms", "type"=>"double"}
  ],
  "values" => [
    ["2023-10-23T12:15:03.360Z", "172.21.2.162", 3450233, "Connected to 10.1.0.3", 3.5],
    ...
  ]
}

适合需要控制返回格式、自己做映射/导出(如 CSV)的场景。

三、方式二:ES|QL Helper(拿到"即用型" Ruby 对象)

ruby 复制代码
require 'elasticsearch/helpers/esql_helper'

response = Elasticsearch::Helpers::ESQLHelper.query(client, query)
response.each { |row| puts row }

输出示意(每行都是 Hash)

ruby 复制代码
{"duration_ms"=>3.5, "message"=>"Connected to 10.1.0.3",
 "event.duration"=>3450233, "client.ip"=>"172.21.2.162",
 "@timestamp"=>"2023-10-23T12:15:03.360Z"}

列级类型转换(parser)

给每个列名配一个 Proc,在"映射到对象"的同时完成转换:

ruby 复制代码
require 'elasticsearch/helpers/esql_helper'
require 'ipaddr'
require 'date'

parser = {
  '@timestamp'    => ->(t) { DateTime.parse(t) },
  'client.ip'     => ->(i) { IPAddr.new(i) },
  'event.duration'=> ->(d) { d.to_s }
}

rows = Elasticsearch::Helpers::ESQLHelper.query(client, query, parser: parser)
puts rows.first
# => {"duration_ms"=>3.5, "message"=>"Connected ...",
#     "event.duration"=>"3450233", "client.ip"=>#<IPAddr: IPv4:...>,
#     "@timestamp"=>#<DateTime: 2023-10-23T12:15:03+00:00 ...>}

这样你在业务层直接面对 Ruby 类型,而不是原始字符串。

四、用 elastic-esql 构建 ES|QL(更易读、可组合)

ruby 复制代码
require 'elasticsearch'
require 'elastic/esql'

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

query = Elastic::ESQL.from(index)
                     .sort('@timestamp').desc
                     .where('event_duration > 5000000')
                     .limit(3)
                     .eval({ duration_ms: 'ROUND(event_duration/1000000.0, 1)' })

client.esql.query(body: { query: query })

查看生成的 ES|QL 字符串:

ruby 复制代码
query.to_s
# "FROM sample_data | SORT @timestamp DESC | WHERE event_duration > 5000000 | LIMIT 3 | EVAL duration_ms = ROUND(event_duration/1000000.0, 1)"

该库不依赖 elasticsearch-ruby,本质是一个查询构建器 ;写好 query 后可直接喂给 client.esql.query

五、防注入:参数化查询是必须的

和 SQL 一样,不要把用户输入直接拼进查询 。ES|QL 支持把不可信数据作为 params 单独传入,用 ? 占位:

ruby 复制代码
def find_employee_by_name(name)
  query = Elastic::ESQL.from('employees')
                       .keep('first_name', 'last_name', 'height')
                       .where('first_name == ?')

  @client.esql.query(body: { query: query, params: [name] })
end

params 会按顺序替换 ?,从而避免代码注入风险。

六、选择响应格式:JSON / CSV / Text

  • 默认 :JSON Hash(columns + values
  • 也可:请求里指定 CSV、text 等格式,并控制分隔符、locale 等,方便导出或兼容旧系统。
  • 使用 Helper 时通常保留默认 JSON,然后映射成 Ruby 对象。

七、实战建议(踩坑少、性能好)

  • 统一入口 :面向业务推荐使用 ES|QL Helper,保持代码简洁一致。
  • 类型就地转换 :用 parser 在 Helper 层完成时间/IP/数值转换,避免在业务处"到处 parse"。
  • 参数化一律默认开启 :所有用户输入都走 ? + params,别拼字符串。
  • 日志与观测:对关键 ES|QL 查询加上上下文(如 request id),便于排障与压测对比。
  • 导出/集成 :需要 CSV 或文本格式时,直接用原生 API 选对应 format,少写转换代码。
  • Query Builder 团队规范 :针对长查询/拼装查询,统一使用 elastic-esql,可读可测试。

八、完整小结

  • 原生 API:最强灵活性,可控返回格式,但需要自己解析。
  • ES|QL Helper :即开即用,返回 Ruby Hash/Array,并支持列级 Proc 转换。
  • elastic-esql:优雅构建查询字符串,适合复杂、可组合的场景。
  • 安全务必参数化 ,把用户输入放到 params

把这三者配起来,你就能在 Ruby 环境下把 ES|QL 用得又快又稳、又安全又优雅。

相关推荐
猿java2 小时前
Elasticsearch有哪几种分页方式?该如何选择?
后端·elasticsearch·架构
Elasticsearch1 天前
推进数据成熟度旅程的 3 个步骤
elasticsearch
Elasticsearch1 天前
用数据驱动的洞察释放业务增长:来自 IT 领导者的 5 个经验
elasticsearch
Elasticsearch1 天前
Elasticsearch:什么是神经网络?
elasticsearch
chenglin0162 天前
ES_索引模板
大数据·elasticsearch·jenkins
Elasticsearch2 天前
传统 AI 与生成式 AI:IT 领导者指南
elasticsearch
Hello.Reader2 天前
Elasticsearch Rails 集成(elasticsearch-model / ActiveRecord)
大数据·elasticsearch·jenkins
果子⌂2 天前
Git+Jenkins实战(一)
运维·git·jenkins
chenglin0162 天前
Logstash——输出(Output)
运维·jenkins