加载中

使用 ES|QL REST API

提示

使用 ES|QL 搜索和过滤教程提供了对 ES|QL _query API 的实操介绍。

_query APIquery 参数中接受一个 ES|QL 查询字符串,运行它并返回结果。例如

				POST /_query?format=txt
					{
  "query": "FROM library | KEEP author, name, page_count, release_date | SORT page_count DESC | LIMIT 5"
}
		

返回

     author      |        name        |  page_count   | release_date
-----------------+--------------------+---------------+------------------------
Peter F. Hamilton|Pandora's Star      |768            |2004-03-02T00:00:00.000Z
Vernor Vinge     |A Fire Upon the Deep|613            |1992-06-01T00:00:00.000Z
Frank Herbert    |Dune                |604            |1965-06-01T00:00:00.000Z
Alastair Reynolds|Revelation Space    |585            |2000-03-15T00:00:00.000Z
James S.A. Corey |Leviathan Wakes     |561            |2011-06-02T00:00:00.000Z
		

我们建议使用 Console 来运行 ES|QL 查询 API,因为它具有丰富的自动完成功能。

创建查询时,使用三引号 (""") 可以让你使用诸如引号 (") 之类的特殊字符而无需对其进行转义。它们还使得编写多行请求变得更加容易。

				POST /_query?format=txt
					{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """
}
		

ES|QL 可以用以下人类可读格式和二进制格式返回数据。你可以通过在 URL 中指定 format 参数或通过设置 AcceptContent-Type HTTP 头来设置格式。

例如

				POST /_query?format=yaml
					{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """
}
		
注意

URL 参数优先于 HTTP 头。如果两者都未指定,则响应将以与请求相同的格式返回。

包含元数据的完整响应。适用于自动解析。

format HTTP 头 描述
json application/json JSON (JavaScript Object Notation) 人类可读格式
yaml application/yaml YAML (YAML Ain’t Markup Language) 人类可读格式

仅查询结果,不包含元数据。适用于快速、手动的数据预览。

format HTTP 头 描述
csv text/csv 逗号分隔值
tsv text/tab-separated-values 制表符分隔值
txt text/plain 类似 CLI 的表示形式
md text/markdown Markdown / GitHub 风格的管道表格
提示

csv 格式接受一个格式化 URL 查询属性 delimiter,用于指示应用哪个字符来分隔 CSV 值。它的默认值为逗号 (,) 且不能取以下任何值:双引号 (")、回车符 (\r) 和换行符 (\n)。制表符 (\t) 也不能使用。请改用 tsv 格式。

提示

md 格式始终包含表头行。请求 header=absent(例如通过 Accept: text/markdown; header=absent)会返回 400 错误,这与支持 header=presentheader=absentcsvtsvtxt 不同。

紧凑的二进制编码。供应用程序使用。

format HTTP 头 描述
cbor application/cbor 简明二进制对象表示法
smile application/smile 类似于 CBOR 的 Smile 二进制数据格式
arrow application/vnd.apache.arrow.stream 实验性。 Apache Arrow 数据帧,IPC 流式传输格式

filter 参数中指定一个 Query DSL 查询,以过滤 ES|QL 查询所运行的文档集。

				POST /_query?format=txt
					{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """,
  "filter": {
    "range": {
      "page_count": {
        "gte": 100,
        "lte": 200
      }
    }
  }
}
		

返回

    author     |                name                |  page_count   | release_date
---------------+------------------------------------+---------------+------------------------
Douglas Adams  |The Hitchhiker's Guide to the Galaxy|180            |1979-10-12T00:00:00.000Z
		

filter 参数跳过整个索引时,它可以从结果集中剔除列。这对于解决不同索引属性之间的类型冲突非常有用。

例如,如果数据流中的几天数据使用了不正确的类型进行索引,你可以使用过滤器来排除不正确的范围。这允许 ES|QL 在不更改源模式的情况下,对剩余数据使用正确的类型。

考虑查询具有 f1 属性的 index-1 和具有 f2 属性的 index-2

使用过滤器时,以下查询仅返回 f1

				POST /_query?format=txt
					{
  "query": "FROM index-*",
  "filter": {
    "term": {
      "f1": "*"
    }
  }
}
		

使用 WHERE 子句会同时返回 f1f2

				POST /_query?format=txt
					{
  "query": "FROM index-* WHERE f1 is not null"
}
		

默认情况下,ES|QL 以行的形式返回结果。例如,FROM 将每个单独的文档返回为一行。对于 jsonyamlcborsmile 格式,ES|QL 可以以列式方式返回结果,其中一行代表结果中某列的所有值。

				POST /_query?format=json
					{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """,
  "columnar": true
}
		

返回

{
  "took": 28,
  "is_partial": false,
  "documents_found": 5,
  "values_loaded": 20,
  "columns": [
    {"name": "author", "type": "text"},
    {"name": "name", "type": "text"},
    {"name": "page_count", "type": "integer"},
    {"name": "release_date", "type": "date"}
  ],
  "values": [
    ["Peter F. Hamilton", "Vernor Vinge", "Frank Herbert", "Alastair Reynolds", "James S.A. Corey"],
    ["Pandora's Star", "A Fire Upon the Deep", "Dune", "Revelation Space", "Leviathan Wakes"],
    [768, 613, 604, 585, 561],
    ["2004-03-02T00:00:00.000Z", "1992-06-01T00:00:00.000Z", "1965-06-01T00:00:00.000Z", "2000-03-15T00:00:00.000Z", "2011-06-02T00:00:00.000Z"]
  ]
}
		

要为查询设置默认时区,请在请求体中使用 time_zone 参数。如果未指定,默认时区为 UTC。

该参数既接受偏移量(例如 +01:00),也接受时区 ID(例如 Europe/Paris)。

这将影响以下内容

  • 处理日期的函数(如 DATE_DIFF)将在可能的情况下使用它。
    • 如果函数具有自定义的 time_zone 参数,则该参数优先
  • 日期值的 API 响应格式将根据指定的时区进行格式化。这取决于所使用的格式。

例如,此查询

				POST /_query
					{
  "time_zone": "Europe/Paris",
  "query": """
    ROW date_string = "2023-01-15T00:00:00.000"
    | EVAL date = date_parse(date_string)
  """
}
		

将返回

{
  "took": 28,
  "is_partial": false,
  "documents_found": 2,
  "values_loaded": 2,
  "columns": [
    {"name": "date_string", "type": "keyword"},
    {"name": "date", "type": "date"},
  ],
  "values": [
    ["2023-01-15T00:00:00.000", "2023-01-15T00:00:00.000+01:00"]
  ]
}
		

在请求体中使用 locale 参数以根据区域设置的惯例返回格式化的结果(尤其是日期)。如果未指定 locale,则默认为 en-US(英语)。请参考 JDK 支持的区域设置

语法:locale 参数接受格式为 xyxy-XY 的语言标记(不区分大小写)。

例如,要返回法语的月份名称

				POST /_query
					{
  "locale": "fr-FR",
  "query": """
    ROW birth_date_string = "2023-01-15T00:00:00.000Z"
    | EVAL birth_date = date_parse(birth_date_string)
    | EVAL month_of_birth = DATE_FORMAT("MMMM",birth_date)
    | LIMIT 5
  """
}
		

使用 approximation 参数为 STATS 查询启用快速近似计算。如果未指定,则默认为 false

例如

				POST /_query
					{
  "approximation": true,
  "query": """
    FROM web_traffic
    | STATS total_hits = COUNT(), avg_load_time = AVG(page_load_ms)
  """
}
		

对于更高级的设置,请使用查询近似设置对象。

你可以使用参数将查询逻辑与其数据分离,而不是将值直接嵌入到查询字符串中。当查询包含用户输入时,这种方法可以防止注入攻击,并使查询能够使用不同的值重复使用。

ES|QL 支持值参数和标识符参数

  • (?) 插入字面量。字符串带引号,数字保持原样。
  • 标识符 (??) 插入字段名或函数名。

这些参数可以是命名的、位置的或匿名的

  • 命名 (?name, ??name) 按名称与参数匹配。
  • 位置 (?1, ??2) 按数组中的位置与参数匹配。
  • 匿名 (?, ??) 按它们在查询中出现的顺序与参数匹配。
重要提示

不在同一个查询中混用参数风格。例如,不能将命名的 ?name 与位置的 ??1 混用。选择一种风格并在值参数和标识符参数中一致地使用它。

提示

我们建议在 9.1 及更高版本中使用 ?? 语法替代。

语法

风格 占位符 params 格式
命名 ?name [{"name": value}, ...]
位置 ?1, ?2 [value1, value2, ...]
匿名 ? [value1, value2, ...](按顺序消耗)
				POST /_query
					{
  "query": """
    FROM library
    | WHERE page_count > ?min_pages AND author == ?author
    | KEEP author, name, page_count
    | SORT page_count DESC
  """,
  "params": [{"min_pages" : 300}, {"author" : "Frank Herbert"}]
}
		
  1. 命名占位符 ?min_pages?author 标记了值被替换的位置
  2. params 中的每个对象将名称映射到其值

你还可以按位置引用参数

				POST /_query
					{
  "query": """
    FROM library
    | WHERE page_count > ?1 AND author == ?2
    | KEEP author, name, page_count
    | SORT page_count DESC
  """,
  "params": [300, "Frank Herbert"]
}
		
  1. ?1 指代第一个参数,?2 指代第二个参数
  2. 值作为简单的数组提供,按位置匹配

?? 占位符允许你在 params 中将字段名和函数名作为纯字符串传递,而无需将其标注为标识符。

我们建议使用此语法代替原有的 ? 语法。

语法

风格 占位符 params 格式
命名 ??name [{"name": "field_name"}, ...]
位置 ??1, ??2 ["field_name", ...]
匿名 ?? ["field_name", ...](按顺序消耗)

此查询为聚合函数、字段和分组使用了命名的标识符参数

				POST /_query?format=txt
					{
  "query": """
    FROM sample_data
    | STATS result = ??agg_fn(??field) BY ??group_by
    | SORT ??group_by
  """,
  "params": [{"agg_fn": "avg"}, {"field": "event.duration"}, {"group_by": "client.ip"}]
}
		
  1. ??agg_fn 作为函数名插入,??field??group_by 作为字段名插入
  2. 参数值作为标识符替换,而不是作为带引号的字符串

对于位置参数,占位符通过其在数组中的位置引用参数

				POST /_query?format=txt
					{
  "query": """
    FROM sample_data
    | STATS result = ??1(??2) BY ??3
    | SORT ??3
  """,
  "params": ["avg", "event.duration", "client.ip"]
}
		
  1. ??1 是第一个参数(函数名),??2 是第二个(字段),??3 是第三个(分组字段)
  2. 标识符名称的简单数组

对于匿名参数,每个 ?? 按顺序消耗下一个参数

				POST /_query?format=txt
					{
  "query": """
    FROM sample_data
    | STATS result = ??(??) BY ??
    | SORT ??
  """,
  "params": ["avg", "event.duration", "client.ip", "client.ip"]
}
		
  1. 每个 ?? 被数组中的下一个参数替换
  2. client.ip 出现两次,因为 SORT ?? 消耗了一个单独的参数

对于像 car.make 这样由点分隔的字段名,你可以分别对每个段进行参数化。当相同的命名空间前缀适用于多个字段时,这非常有用

				POST /_query?format=txt
					{
  "query": """
    FROM persons
    | WHERE ??namespace.??field == ?value
    | KEEP ??namespace.??field, ??namespace.??model, ??sort_field
    | SORT ??sort_field
  """,
  "params": [{"namespace": "car"}, {"field": "make"}, {"value": "Tesla"}, {"model": "model"}, {"sort_field": "first_name"}]
}
		
  1. ??namespace.??field 被作为限定字段名 car.make 插入
  2. 每个标识符参数提供点分隔名称的一个段

你可以在同一个查询中混合使用这两种参数类型。当要过滤的字段和过滤值都是动态的时,这非常有用。

				POST /_query?format=txt
					{
  "query": """
    FROM sample_data
    | WHERE ??field == ?value
    | KEEP ??field
  """,
  "params": [{"field": "client.ip"}, {"value": "192.168.1.1"}]
}
		
  1. ??field 是一个标识符参数(字段名),?value 是一个值参数(过滤值)
  2. 这两种参数类型都可以被命名并一起提供

ES|QL 异步查询 API 允许你异步执行查询请求、监控其进度并在结果可用时检索结果。

执行 ES|QL 查询通常非常快,但在跨大型数据集或冻结数据进行查询时可能需要一些时间。为避免长时间等待,请运行异步 ES|QL 查询。

异步查询 API 发起的查询可能会也可能不会返回结果。wait_for_completion_timeout 属性决定等待结果的时长。如果在此时间内结果不可用,则会返回一个查询 ID,稍后可用于检索结果。例如

				POST /_query/async
					{
  "query": """
    FROM library
    | EVAL year = DATE_TRUNC(1 YEARS, release_date)
    | STATS MAX(page_count) BY year
    | SORT year
    | LIMIT 5
  """,
  "wait_for_completion_timeout": "2s"
}
		

如果在给定的超时期间内(本例中为 2 秒)结果不可用,则不返回结果,而是返回包含以下内容的响应

  • 查询 ID
  • 值为 trueis_running,表示查询正在进行中

查询继续在后台运行,不会阻塞其他请求。

{
  "id": "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  "is_running": true
}
		

要检查异步查询的进度,请使用带有查询 ID 的 ES|QL 异步查询获取 API。在 wait_for_completion_timeout 参数中指定你希望等待完整结果的时长。

				GET /_query/async/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=?wait_for_completion_timeout=30s
		

如果响应的 is_running 值为 false,则表示查询已完成并返回了结果,同时附带查询的耗时 (took)。

{
  "is_running": false,
  "took": 48,
  "columns": ...
}
		

要停止正在运行的异步查询并返回到目前为止计算出的结果,请使用带有查询 ID 的 异步停止 API

				POST /_query/async/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=/stop
		

查询将被停止,响应将包含到目前为止计算出的结果。响应格式与 get API 相同。

{
  "is_running": false,
  "took": 48,
  "is_partial": true,
  "columns": ...
}
		

即使查询已经完成,只要在 keep_alive 窗口内,也可以使用此 API 检索结果。is_partial 字段指示结果的完整性。值为 true 意味着结果可能不完整。

keep_alive 期间结束之前,使用 ES|QL 异步查询删除 API 删除异步查询。如果查询仍在运行,Elasticsearch 将将其取消。

				DELETE /_query/async/FmdMX2pIang3UWhLRU5QS0lqdlppYncaMUpYQ05oSkpTc3kwZ21EdC1tbFJXQToxOTI=
		
注意

你还将在响应的 X-Elasticsearch-Async-IdX-Elasticsearch-Async-Is-Running HTTP 头中分别收到异步 ID 和运行状态。如果你使用诸如 txtcsvtsv 之类的表格文本格式,这会非常有用,因为你在响应体中收不到这些字段。

除了 Elasticsearch 传统的耗时 took 之外,ES|QL 还返回 documents_foundvalues_loaded,你可以将它们视为 Elasticsearch 为运行查询所必须付出努力的粗略代理指标。通常,数字越大意味着查询花费的精力越多。

documents_found 是运行查询必须查找的文档数量。如果该值较低,则说明 Elasticsearch 能够有效地利用其搜索索引来返回结果。少数查询(如 FROM idx | STATS COUNT(*))无需查看任何文档即可运行。它们会针对每个计数俏皮地报告一个“找到的”文档。

values_loaded 是运行查询所加载的值的数量。如果 Elasticsearch 必须为每个文档加载一个值(就像 FROM idx | STATS BY DATE_TRUNC(1 hour, @timestamp) 那样),这将与 documents_found 相同。如果 Elasticsearch 必须为每个文档加载许多字段,它将是 documents_found 的许多倍。同样,更大的数字通常意味着查询花费了更多的精力。

尽管 documents_foundvalues_loaded 很高,许多查询仍然会很快。由于各种原因,有些查询即使在 documents_foundvalues_loaded 较低的情况下也会很慢

  • 查询超级快或超级慢。
  • 某些值加载非常快(如 @timestamp),而其他值加载慢得多(如 text 字段)。
  • 某些函数相当快(如 +DATE_TRUNCBUCKET 等)。
  • 某些命令相当重(如 GROK)。
© . This website operates independently and is not affiliated with or endorsed by Elasticsearch B.V. All brand names, logos, and trademarks are the property of their respective owners.