elasticsearch-esql

elasticsearch-esql

熱門

執行 ES|QL (Elasticsearch 查詢語言) 查詢,當使用者想要查詢 Elasticsearch 資料、分析日誌、彙總指標、探索資料,或從 ES|QL 結果建立圖表與儀表板時使用。

542星標
44分支
更新於 2026/7/22
SKILL.md
唯讀
名稱
elasticsearch-esql
描述

執行 ES|QL (Elasticsearch 查詢語言) 查詢,當使用者想要查詢 Elasticsearch 資料、分析日誌、彙總指標、探索資料,或從 ES|QL 結果建立圖表與儀表板時使用。

Elasticsearch ES|QL

對 Elasticsearch 執行 ES|QL 查詢。

什麼是 ES|QL?

ES|QL (Elasticsearch 查詢語言) 是 Elasticsearch 的管線式查詢語言。它不同於

  • Elasticsearch Query DSL (JSON 格式)
  • SQL
  • EQL (事件查詢語言)

ES|QL 使用管線 (|) 串聯指令:
FROM index | WHERE condition | STATS aggregation BY field | SORT field | LIMIT n

先決條件: ES|QL 需要在查詢的索引上啟用 _source。停用 _source 的索引(例如
"_source": { "enabled": false })會導致 ES|QL 查詢失敗。

版本相容性: ES|QL 於 8.11 推出(技術預覽),並在 8.14 正式 GA。後續版本新增了
LOOKUP JOIN (8.18+)、MATCH (8.17+) 和 INLINE STATS (9.2+) 等功能。在 8.18 之前的叢集上,
使用 ENRICH 作為 LOOKUP JOIN 的替代方案(請參閱生成提示)。INLINE STATS 和計數器欄位 RATE()
9.2 之前沒有替代方案。請查閱 references/esql-version-history.md 了解各版本的功能可用性。

叢集偵測: 使用 GET / 的回應來判斷叢集類型和版本:

  • build_flavor: "serverless" — Elastic Cloud Serverless。version.number 追蹤正在開發中的堆疊線(主線的下一個次要版本),因此僅進行 semver 比較的客戶端可能會將 Serverless 視為「最新」。不要
    使用 version.number 來判斷功能:如果 build_flavor"serverless",則假設所有 GA 和預覽版 ES|QL 功能
    皆可使用。
  • build_flavor: "default" — 自管或 Elastic Cloud Hosted。使用 version.number 判斷功能可用性。
  • 快照版本version.number 類似 9.4.0-SNAPSHOT。移除 -SNAPSHOT 後綴,並使用
    主版本.次版本進行版本檢查。快照版本包含該版本的所有功能,以及可能尚未發布的開發中功能 — 如果查詢因未知函數/指令而失敗,可能只是該功能尚未加入。
    Elastic 員工通常使用快照版本進行測試。

環境設定

請參閱 Environment Setup 了解完整的連線設定選項(Elastic Cloud、
直接 URL、基本驗證、本機開發)。

執行 node scripts/esql.js test 來驗證連線。如果測試失敗,請引導使用者參考環境設定
指南,然後停止。在成功連線測試之前,不要嘗試進一步探索。

使用方式

取得索引資訊(用於結構描述探索)

node scripts/esql.js indices                    # 列出所有索引
node scripts/esql.js indices "logs-*"           # 列出符合的索引
node scripts/esql.js schema "logs-2024.01.01"   # 取得索引的欄位對應

執行原始 ES|QL

node scripts/esql.js raw "FROM logs-* | STATS count = COUNT(*) BY host.name | SORT count DESC | LIMIT 5"

以 TSV 格式輸出執行

node scripts/esql.js raw "FROM logs-* | STATS count = COUNT(*) BY component | SORT count DESC" --tsv

TSV 輸出選項:

  • --tsv-t:以 Tab 分隔值輸出(乾淨,無裝飾)
  • --no-header:省略標題列

測試連線

node scripts/esql.js test

使用指南

  1. 偵測部署類型:始終先執行 node scripts/esql.js test。這會偵測部署是
    Serverless 專案(所有功能皆可用)還是有版本的叢集(功能取決於版本)。來自 GET /build_flavor
    欄位是權威信號 — 如果等於 "serverless",則忽略報告的版本號碼並
    自由使用所有 ES|QL 功能。

  2. 探索結構描述(必要 — 切勿猜測索引或欄位名稱):

    node scripts/esql.js indices "pattern*"
    node scripts/esql.js schema "index-name"
    

    在生成查詢之前,務必先執行結構描述探索。索引名稱和欄位名稱因部署而異,無法
    可靠地猜測。即使是常見的資料(例如 "logs")也可能存在於名為 logs-testlogs-app-*
    application_logs 的索引中。欄位名稱可能使用 ECS 點記法(source.ipservice.name)或扁平的自訂名稱 — 唯一
    知道的方法就是檢查。

    偏好簡單: 除非使用者明確要求跨多個來源的資料,否則查詢單一索引。不要
    使用 COALESCE 合併不同結構描述的索引,除非特別要求 — 為問題挑選最相關的單一
    索引。當多個索引包含類似資料時,優先選擇結構描述最完整的索引來完成任務。

    schema 指令會報告索引模式。如果顯示 Index mode: time_series,輸出會包含資料
    串流名稱和可複製貼上的 TS 語法 — 使用 TS <data-stream>(而非 FROM)、TBUCKET(interval)(而非
    DATE_TRUNC),並將計數器欄位包裹在 SUM(RATE(...)) 中。在撰寫任何時間序列查詢之前,請先閱讀
    Generation Tips 中的完整 TS 章節。您也可以直接透過 Elasticsearch 索引設定 API 檢查索引
    模式:

    curl -s "$ELASTICSEARCH_URL/<index-name>/_settings/index.mode" -H "Authorization: ApiKey $ELASTICSEARCH_API_KEY"
    

    對於 9.4+ 的 TSDS 索引,偏好使用語言內建的探索指令 METRICS_INFOTS_INFO(皆為 GA),而非
    檢查對應 — 它們會直接列舉指標目錄和每個時間序列的維度標籤。兩者都必須
    跟在 TS 之後,且必須在 STATS/SORT/LIMIT 之前。請參閱
    Time Series Queries

    node scripts/esql.js raw "TS metrics-tsds | METRICS_INFO | SORT metric_name" --tsv
    node scripts/esql.js raw "TS metrics-tsds | TS_INFO | KEEP metric_name, dimensions | SORT metric_name" --tsv
    
  3. 為任務選擇正確的 ES|QL 功能:在撰寫查詢之前,將使用者的意圖與最
    合適的 ES|QL 功能配對。偏好單一進階查詢,而非多個基本查詢。

    • "尋找模式"、"分類"、"分組相似訊息" → CATEGORIZE(field)
    • "突波"、"驟降"、"異常"、"X 何時改變" → CHANGE_POINT value ON key
    • "隨時間的趨勢"、"時間序列" → STATS ... BY BUCKET(@timestamp, interval) 或 TSDB 使用 TS
    • "PromQL"、"Prometheus 查詢/儀表板/警示"、sum by (instance) (...)、標籤匹配器如 {cluster="prod"}
      PROMQL 來源指令(9.4+ 預覽);請參閱 PROMQL Command。偏好使用 TS 進行原生
      ES|QL 表達。
    • "搜尋"、"尋找符合的文件" → MATCH(預設)、QSTR(進階布林)、KQL(Kibana 遷移)。對於
      內容/文件相關性搜尋,請遵循 ES|QL Search Strategy
    • "計數"、"平均"、"細分" → 使用彙總函數的 STATS
  4. 在生成查詢之前閱讀參考資料

    • Generation Tips - 關鍵模式(TS/TBUCKET/RATE、每個彙總的 WHERE、LOOKUP JOIN、
      CIDR_MATCH)、常見範本和歧義處理
    • Time Series Queries - 在任何 TS 查詢之前閱讀:內/外層彙總
      模型、TBUCKET 語法、RATE 限制
    • PROMQL Command在任何 PROMQL 查詢之前閱讀:選項、輸出結構描述、
      限制,以及 PROMQLTS 的決策矩陣(9.4+ 預覽)
    • ES|QL Complete Reference - 所有指令和函數的完整語法
    • ES|QL Search Strategy — 用於內容/文件相關性搜尋(檢索 →
      融合 → 重新排序)
    • ES|QL Search Reference — 用於全文搜尋函數語法(MATCH、QSTR、KQL、
      評分)
  5. 生成查詢,遵循 ES|QL 語法。偏好最簡單的查詢來回答問題 — 除非使用者要求,否則不要新增
    額外的索引、欄位或轉換。僅在 KEEP 中包含直接回答問題的欄位。不要新增超出使用者指定的額外篩選條件(例如,當使用者只說 "errors" 時,不要新增
    OR level == "ERROR")。

    • FROM index-pattern(或時間序列索引使用 TS index-pattern)開頭
    • 新增 WHERE 進行篩選(9.3+ 使用 TRANGE 進行時間範圍)
    • 使用 EVAL 進行計算欄位
    • 使用 STATS ... BY 進行彙總
    • 對於時間序列指標:計數器使用 TS 搭配 SUM(RATE(...)),量規使用 AVG(...),並使用 TBUCKET(interval)
      進行時間分桶 — 請參閱 Generation Tips 中的 TS 章節,了解三個關鍵語法規則
    • 若要偵測突波、驟降或異常,請在時間分桶彙總後使用 CHANGE_POINT
    • 視需要新增 SORTLIMIT
  6. 使用 TSV 標誌執行

    node scripts/esql.js raw "FROM index | STATS count = COUNT(*) BY field" --tsv
    

ES|QL 快速參考

版本可用性: 本節為求可讀性省略了版本註解。請查閱
ES|QL Version History 了解各 Elasticsearch 版本的功能可用性。

基本結構

FROM index-pattern
| WHERE condition
| EVAL new_field = expression
| STATS aggregation BY grouping
| SORT field DESC
| LIMIT n

常見模式

篩選並限制:

FROM logs-*
| WHERE @timestamp > NOW() - 24 hours AND level == "error"
| SORT @timestamp DESC
| LIMIT 100

按時間彙總:

FROM metrics-*
| WHERE @timestamp > NOW() - 7 days
| STATS avg_cpu = AVG(cpu.percent) BY bucket = DATE_TRUNC(1 hour, @timestamp)
| SORT bucket DESC

前 N 筆計數:

FROM web-logs
| STATS count = COUNT(*) BY response.status_code
| SORT count DESC
| LIMIT 10

文字搜尋 (8.17+): 使用 MATCH 作為全文搜尋的預設方式,而非 LIKE/RLIKE — 它明顯更快
且支援相關性評分。對 text 欄位使用 MATCH 通常就足夠了 — 除非使用者明確要求篩選,否則不要
MATCH 旁邊新增冗餘的關鍵字相等篩選(例如 category == "X")。僅在需要進階布林邏輯、
萬用字元或單一表達式中的多欄位搜尋時才使用 QSTRMATCH 的第一個引數必須是一個真實的欄位名稱 — 不是列出多個欄位的字串(例如 "title,content"
也不是多個欄位引數;使用 MATCH(a, "q") OR MATCH(b, "q") 組合欄位。KQL 從 8.18/9.0+ 開始可用。
對於內容/文件搜尋使用案例,請遵循 ES|QL Search Strategy。請參閱
ES|QL Search Reference 了解完整的函數指南。

FROM documents METADATA _score
| WHERE MATCH(content, "search terms")
| SORT _score DESC
| LIMIT 20

字串擷取: 使用 DISSECT 進行結構化的分隔符號模式(偏好 — 產生具名欄位),以及
GROK 進行基於正規表示式的擷取。對於簡單情況,使用 SUBSTRING(s, start, len) 進行固定位置擷取、
SPLIT(s, delim) 分割成多值、LOCATE(substr, s) 尋找字元位置。SPLIT 回傳
多值 — 使用 MV_FIRSTMV_LASTMV_SLICE 選取元素。INSTRSTRPOS 不存在 — 使用
LOCATEREGEXP_EXTRACT 不存在 — 使用 GROK

// 使用 DISSECT 從電子郵件中擷取網域(偏好 — 產生具名欄位)
FROM customers
| DISSECT email "%{local}@%{domain}"
| STATS count = COUNT(*) BY domain

// 替代方案:使用 SPLIT 從電子郵件中擷取網域
FROM customers
| EVAL domain = MV_LAST(SPLIT(email, "@"))
| STATS count = COUNT(*) BY domain

// 解析 HTTP 日誌行
FROM logs-*
| DISSECT message "%{method} %{path} %{status_text}"
| KEEP @timestamp, method, path, status_text

日誌分類 (Platinum 授權): 使用 CATEGORIZE 自動將日誌訊息聚類成模式群組。在探索或尋找非結構化文字中的模式時,偏好此方式而非執行多個 STATS ... BY field 查詢。

FROM logs-*
| WHERE @timestamp > NOW() - 24 hours
| STATS count = COUNT(*) BY category = CATEGORIZE(message)
| SORT count DESC
| LIMIT 20

變異點偵測 (Platinum 授權): 使用 CHANGE_POINT 偵測指標序列中的突波、驟降和趨勢轉變。偏好此方式而非手動檢查時間分桶計數。

FROM logs-*
| STATS c = COUNT(*) BY t = BUCKET(@timestamp, 30 seconds)
| SORT t
| CHANGE_POINT c ON t
| WHERE type IS NOT NULL

時間序列指標: 使用 TS 時,使用 TRANGE 進行時間篩選(9.3+)或完全省略 — 不要
TBUCKET 旁邊新增冗餘的 WHERE @timestamp > NOW() - ...TBUCKET 持續時間定義了彙總視窗。

// 計數器指標:SUM(RATE(...)) 搭配 TBUCKET(duration)
TS metrics-tsds
| WHERE TRANGE(1 hour)
| STATS SUM(RATE(requests)) BY TBUCKET(1 hour), host

// 量規指標:AVG(...) — 不需要 RATE
TS metrics-tsds
| STATS avg_cpu = AVG(cpu) BY service.name, bucket = TBUCKET(5 minutes)
| SORT bucket

使用 PromQL 語法的時間序列 (9.4+ 預覽): 當使用者明確要求 PromQL、
參考 Prometheus 語法(sum by (instance) (...)、標籤匹配器如 {cluster="prod"})或正在
遷移 Prometheus 儀表板或警示時,使用 PROMQL 來源指令。PROMQL 指令接受標準 PromQL,並可選用 indexstep
bucketsstartendscrape_interval 選項,並產生一個表格供 ES|QL 管線的其餘部分
處理。範圍選擇器為選用 — 省略時,視窗為 max(step, scrape_interval)。否則偏好使用 TS
(9.4 中 GA)。PROMQL 支援群組修飾符、集合運算子(or/and/unless)或函數如
histogram_quantilepredict_linearlabel_join — 對於這些情況,請改用 TS。請參閱
PROMQL Command 了解完整參考。

// 適應性 Kibana 查詢 — 日期選擇器驅動時間範圍和步長
PROMQL index=metrics-* sum by (instance) (rate(http_requests_total))

// 具名結果,使用 ES|QL 後處理
PROMQL index=k8s step=1h bytes=(max by (cluster) (network.bytes_in))
| STATS max_bytes = MAX(bytes) BY cluster
| SORT cluster

使用 LOOKUP JOIN 的資料豐富化: 基本的 ON 子句透過名稱匹配兩個索引中的欄位
LOOKUP JOIN idx ON field_name)。當聯結鍵在來源中有不同名稱時,先使用 RENAME 對齊
名稱。9.2+ 技術預覽也支援表達式謂詞(ON expr == expr);請參閱
ES|QL Complete Reference 了解詳細資訊。在 LOOKUP JOIN 之後,查詢欄位可透過其原始欄位名稱使用 — 不要
使用表格限定(例如,寫 threat_level,而不是
threat_intel.threat_level)。排序提示: 當問題要求前 N 筆結果時,在 LOOKUP JOIN 之前 進行 SORTLIMIT
以降低豐富化成本。對於一般列表或完整豐富化,將 LOOKUP JOIN 放在 FROM/WHERE 之後。

// 欄位名稱不符 — 在聯結前使用 RENAME
FROM support_tickets
| RENAME product AS product_name
| LOOKUP JOIN knowledge_base ON product_name

// 彙總、限制、然後豐富化(僅前 N 筆)
FROM orders
| STATS total_spent = SUM(total) BY customer_id
| SORT total_spent DESC
| LIMIT 3
| LOOKUP JOIN customers_lookup ON customer_id
| KEEP name, customer_id, total_spent

// 多欄位聯結 (9.2+)
FROM application_logs
| LOOKUP JOIN service_registry ON service_name, environment
| KEEP service_name, environment, owner_team

多值欄位篩選: 使用 MV_CONTAINS 檢查多值欄位是否包含特定值。使用
MV_COUNT 計算值的數量。

// 依多值成員資格篩選
FROM employees
| WHERE MV_CONTAINS(languages, "Python")

// 尋找符合多個值的條目
FROM employees
| WHERE MV_CONTAINS(languages, "Java") AND MV_CONTAINS(languages, "Python")

// 計算多值條目數量
FROM employees
| EVAL num_languages = MV_COUNT(languages)
| SORT num_languages DESC

變異點偵測(替代範例): 當使用者詢問突波、驟降或異常時使用。需要
時間分桶彙總、SORT,然後 CHANGE_POINT

FROM logs-*
| STATS error_count = COUNT(*) BY bucket = DATE_TRUNC(1 hour, @timestamp)
| SORT bucket
| CHANGE_POINT error_count ON bucket AS type, pvalue

完整參考

如需完整的 ES|QL 語法,包括所有指令、函數和運算子,請閱讀:

錯誤處理

當查詢執行失敗時,腳本會回傳:

  • 生成的 ES|QL 查詢
  • Elasticsearch 的錯誤訊息
  • 常見問題的建議

常見問題:

  • 欄位不存在 → 在撰寫查詢之前,務必使用 get_schemalist_indices。切勿猜測欄位或索引
    名稱 — 它們因部署而異。
  • 型別不符 → 使用型別轉換函數(TO_STRING、TO_INTEGER 等)
  • 語法錯誤 → 查閱 ES|QL 參考以確認正確語法。字串務必使用雙引號,絕不使用單引號。
  • 無結果 → 檢查時間範圍和篩選條件
  • 錯誤的函數名稱 → ES|QL 使用底線名稱:STD_DEV() 而非 STDDEV()MEDIAN_ABSOLUTE_DEVIATION() 而非
    MAD()。字串使用 CONCAT(),而非 +。使用 CASE(cond, val, ...) 而非 CASE WHEN...THEN...END
  • 錯誤的日期部分 → DATE_EXTRACT 使用 ES|QL 部分名稱:"hour_of_day" 而非 "hour""day_of_month" 而非 "day"
    "month_of_year" 而非 "month"。日期運算使用 DATE_DIFF("day", start, end),而非減法。

範例

# 結構描述探索
node scripts/esql.js test
node scripts/esql.js indices "logs-*"
node scripts/esql.js schema "logs-2024.01.01"

# 執行查詢
node scripts/esql.js raw "FROM logs-* | STATS count = COUNT(*) BY host.name | LIMIT 10"
node scripts/esql.js raw "FROM metrics-* | STATS avg = AVG(cpu.percent) BY hour = DATE_TRUNC(1 hour, @timestamp)" --tsv