想要亲手体验 Elasticsearch?您可以深入探索 Elasticsearch Labs 代码库 中的示例笔记本,开始 免费的云试用,或者现在就 在本地机器上 试用 Elastic。
ES|QL 在此版本中新增了三项功能,这些功能将彻底改变您建模和查询数据的方式:逻辑 视图(views) 允许您定义一次查询,然后可以通过其名称在任何仪表板或告警中引用它;FROM 子句中的 子查询(subqueries) 让您能够在单个管道中组合具有不兼容 schema 的索引;读时模式(schema-on-read) 允许您针对已索引的数据查询从未映射过的字段,而无需修改映射或重新索引。与这些功能并行的是:timezone support 已升级到 GA,LIMIT BY 原生支持分组 top-N 查询,并且通过 Lucene 结构重用,lookup joins 的速度也得到了提升。每个主要功能都有其专属的深度解析文章,链接如下。

ES|QL 读时模式功能概述:未映射字段、JSON 提取、子查询和逻辑视图,均标记为技术预览。
视图、子查询和读时模式被设计为可以分层组合使用。子查询为每个索引提供了独立的管道。视图则将该子查询封装起来,以便使用者可以通过一个名称来引用它。读时模式允许这些管道访问从未在映射中声明过的字段。最终结果是:一个 FROM view_name 查询能够组合多个服务的数据,规范化它们的 schema,并展示您在 ingest 期间遗漏映射的字段。以下各节中链接了每个功能的深度解析文章。
逻辑视图(Logical views) 是虚拟索引:它们是存储在 Elasticsearch 集群级别的查询定义,您可以在任何 FROM 子句中通过名称引用它们,就像引用真实的索引一样。您可以通过 _query/view REST API 定义一次视图。使用该视图的每个仪表板、告警和即席查询都会自动获取定义更改。视图支持嵌套、跨集群搜索(cross-cluster search) 和专用的 RBAC 权限。
1 PUT _query/view/error_triage
2 {
3 "query": """
4 FROM svc-gateway-*
5 | WHERE http.response.status_code >= 500
6 | KEEP @timestamp, http.response.status_code, url.path, source.ip
7 """
8 }
9
10 FROM error_triage
11 | STATS error_count = COUNT(*) BY url.path
12 | SORT error_count DESC
Kibana Discover 展示了一个三行 ES|QL 查询(FROM error_triage, STATS error_count, SORT error_count DESC),其中自动补全将 error_triage 标记为逻辑视图。结果显示了按服务分类的错误计数的条形图和表格:payments 为 104,gateway 为 37,auth 为 19。
阅读完整的深度解析文章:Elasticsearch ES|QL 视图:一个查询统治十二个仪表板

ES|QL 子查询管道显示索引 A 和索引 B 各自经过 WHERE、EVAL 和 KEEP 阶段,然后通过 UNION ALL 合并成一个统一的结果流。
子查询(Subqueries) 为您提供了组合数据的基本能力:在单个查询中,组合来自多个索引的数据,即使它们具有不同的 schema。每个分支都有自己的 WHERE、EVAL、KEEP,并且优化器会将过滤器独立地推送到每个索引中。结果将通过 UNION ALL 语义进行合并。
1 FROM
2 (FROM svc-gateway-*
3 | WHERE http.response.status_code >= 500
4 | EVAL service = "gateway",
5 error_detail = CONCAT("HTTP ", http.response.status_code::string)
6 | KEEP @timestamp, service, error_detail, source.ip),
7 (FROM svc-payments-*
8 | WHERE transaction.status IN ("failed", "timeout")
9 | EVAL service = "payments",
10 error_detail = transaction.status
11 | KEEP @timestamp, service, error_detail, source.ip),
12 (FROM svc-auth-*
13 | WHERE event.action == "login" AND event.outcome == "failure"
14 | EVAL service = "auth",
15 error_detail = CONCAT(event.action, " ", event.outcome)
16 | KEEP @timestamp, service, error_detail, source.ip)
17 | SORT @timestamp DESC
18 | LIMIT 20阅读完整的深度解析文章:三个索引走进 FROM 子句:Elasticsearch 中的 ES|QL 子查询
未映射字段访问(Unmapped field access) 允许您查询那些从未在映射中声明过的字段,针对索引中已有的数据进行查询,而无需重新索引。SET unmapped_fields="load" 是战略性的抽象:只需一行代码,在 ingest 时遗漏的字段就可以从 _source 中进行查询。JSON_EXTRACT 是更底层的工具,用于从原始 JSON 字符串和扁平化字段中进行精确提取。
1 SET unmapped_fields="load";
2
3 FROM otel-logs-*
4 | WHERE log.level IN ("error", "warn")
5 | STATS errors = COUNT(*), latest = MAX(@timestamp)
6 BY service.name, resource.cost_center
7 | SORT errors DESC
ES|QL 未映射字段行为:默认模式隐藏字段,nullify 模式显示空列,load 模式在查询时从原始源读取字段。
阅读完整的深度解析文章:Elasticsearch ES|QL “读时模式”:您未映射的字段一直都在
SET time_zone 现已普遍可用(GA),为每个 ES|QL 查询带来了时区感知的日期/时间操作。只需在查询级别设置一次,所有 DATE_TRUNC、日期聚合和时间戳输出都将反映本地时区,无需任何后处理。它接受任何 IANA 时区字符串。
1 SET time_zone="America/Los_Angeles";
2
3 FROM error_triage
5| EVAL hour = DATE_TRUNC(1 hour, @timestamp)
5| STATS errors = COUNT(*) BY hour, service
6| SORT hour DESC输出的时间戳将包含时区偏移量(例如,2026-04-09T11:00:00.000-07:00 而不是 ...T18:00:00.000Z)。目前没有针对每个函数的时区参数;SET time_zone 是实现此功能的机制。在 Kibana 中,ES|QL 仪表板面板和 Discover 查询现在可以通过本地营业时间生成时区感知的结果,无需任何后处理。
“显示每个服务的前 3 种错误类型”以前需要进行后处理,因为 SORT 和 LIMIT 是全局应用的,只会给您整体的 Top N,而不是每个分组的 Top N。LIMIT BY 原生地解决了这个问题:
1 FROM error_triage
2 | STATS cnt = COUNT(*) BY service, error_detail
3 | SORT cnt DESC
4 | LIMIT 3 BY service它会为每个不同的 service 值返回前 3 行。数字写在 BY 之前。

ES|QL LIMIT BY 命令将混合行过滤为每个分组的 Top-N 结果,并用结果标注显示每个服务的前 3 种错误类型,无需后处理。
FIRST、LAST、EARLIEST、LATEST (GA) 返回与排序字段的最小值或最大值相关联的值:
1 FROM svc-auth-*
2 | WHERE event.outcome == "failure"
3 | STATS first_seen = FIRST(@timestamp, @timestamp),
4 last_seen = LAST(@timestamp, @timestamp),
5 first_user = EARLIEST(user.name),
6 attempts = COUNT(*)
7 BY source.ip
8 | SORT attempts DESCFIRST 和 LAST 接受两个参数:值字段和排序字段。EARLIEST 和 LATEST 是单参数别名,它们隐式地按 @timestamp 排序,这对于检索时间序列中哪个值首先或最后出现非常有用。
URI_PARTS、USER_AGENT、REGISTERED_DOMAIN 是三个新的管道命令,它们将单个字段扩展为多个结构化输出列:
1 FROM svc-gateway-*
2 | WHERE http.response.status_code >= 400
3 | URI_PARTS parts = url.full
4 | STATS errors = COUNT(*) BY parts.domain, parts.path
5 | SORT errors DESC
6
7 FROM svc-auth-*
8 | USER_AGENT ua = user_agent.original
9 | STATS cnt = COUNT(*) BY ua.name, ua.version语法是 | COMMAND target = source_field。URI_PARTS 会生成 target.domain、target.path、target.scheme、target.port 等。USER_AGENT 会生成 target.name、target.version、target.os.name 等。REGISTERED_DOMAIN 会生成 target.registered_domain、target.top_level_domain 和 target.subdomain。
多项功能已升级为普遍可用(GA),并且 lookup joins 的速度也得到了提升。
_size 元数据:通过 FROM 子句中的 METADATA _size 访问文档大小。Lookup joins 于 9.1 版本引入,并得到了两项显著优化:

ES|QL lookup join 优化:Lucene 结构重用缓存文档值以绕过磁盘读取,单关键字连接使用更快的执行路径以减少每行开销。
keyword 字段(最常见的连接键类型)上的 lookup joins 现在使用 更快的执行路径,减少了每行连接的开销。这两项优化共同使得 lookup joins 在高吞吐量的 enrichment 工作负载中更加实用。
本文重点介绍了查询语言和数据访问功能。ES|QL 还获得了 GA 版的时间序列支持(包括 TS 命令、PromQL 风格的函数以及 rate/changes/cumulative_sum)和 近似查询,用于对大型数据集进行更快的探索性分析,这些内容将在各自的博文中进行介绍。
ES|QL 的开发正在快速推进。路线图包括:
WHERE field IN (FROM other_index | ...) 以及其他相关形式,将组合模型从 FROM 扩展到过滤。JSON_EXTRACT 在 _source 上的变通方法,以解决最常见的读时模式用例。所有主要功能均已在 Elasticsearch 中作为 Tech Preview 提供(视图尚未在 Serverless 中提供)。时区支持、FIRST/LAST/EARLIEST/LATEST、VALUES、MV_EXPAND 和 FORK 已普遍可用。您可以在 Kibana Dev Tools 或 Discover 中试用它们。
我们非常期待您的反馈。如果您遇到问题或有功能请求,请在 GitHub 上提交带有 ES|QL 标签的 issue。
ES|QL 子查询、逻辑视图、JSON 提取、未映射字段访问、LIMIT BY、SPARKLINE、MV_UNION、MV_DIFFERENCE 和 MV_INTERSECTS 均为 Tech Preview 功能。Tech Preview 功能可能会发生变化,并且不受 GA 功能的支持 SLA 覆盖。本文中描述的任何功能或功能的发布和时间安排由 Elastic 自行决定。任何当前不可用的功能或功能可能无法按时交付或根本无法交付。
📡 更多 Elastic & AI 可观测性干货