Kibana 查询语法 KQL
什么是 Kibana 查询语言 (KQL)
Kibana 查询语言(Kibana Query Language,简称 KQL)是一套专为 Kibana 设计的简化查询语法,用于在 Discover、Dashboard 和 Visualize 等应用中快速过滤、搜索 Elasticsearch 数据。KQL 的定位是“类自然语言”,让你无需掌握复杂的 Lucene 或 Elasticsearch Query DSL,就能通过直观的表达式完成绝大多数日常分析任务。
与旧版 Lucene 语法相比,KQL 的主要优势包括:
- 自动识别字段:输入字段名后按冒号,系统会提示可选值。
- 更宽松的引号规则:多数字符串无需加引号,除非包含特殊字符或空格。
- 简化的逻辑运算:
and、or、not直接书写,且支持括号组合。 - 内置函数:提供如
exists、*等简洁的字段存在或匹配判断。
启用 KQL
在 Kibana 界面的搜索框左侧,确认语言切换器处于 KQL 状态。若显示为“Lucene”,点击即可切换。KQL 是当前版本的默认查询语言。
基础语法规则
KQL 表达式由 字段查询 和 自由文本查询 组成,二者可以混合使用,并通过逻辑运算符连接。
自由文本查询
最简单的用法是直接输入一个或多个单词,Kibana 会在所有已索引的字段中搜索这些词。多个单词之间默认为 or 关系,即只要文档的任一字段包含任意一个单词就会被命中。
error timeout
等同于在所有字段中查找包含 “error” 或 “timeout” 的文档。
字段查询
针对特定字段进行精确或模糊匹配,语法为:
字段名:值
示例:
status:200
查找 status 字段值为 200 的文档。
如果字段名包含特殊字符(如 @、.),可以不用引号直接书写,但建议使用反引号包裹避免歧义:
`@timestamp`:"2023-01-01T00:00:00Z"
字符串与短语匹配
无引号字符串
字符串中若不包含空格或特殊字符,可以直接书写:
message:success
带引号的短语
当值包含空格或需要精确匹配整个短语时,使用双引号:
message:"internal server error"
通配符
KQL 支持两种通配符:
*匹配零个或多个字符。?匹配单个字符。
通配符不能作为第一个字符使用(即不能以 * 或 ? 开头),否则会触发性能限制错误。
正确示例:
user:admin*
status:40?
分别匹配 user 字段以 “admin” 开头的值,以及 status 字段为 “400” 到 “409” 之间值(如 401、403 等)。
数字、日期与布尔值查询
数字查询
直接书写数字即可,无需引号:
bytes:>1024
表示 bytes 字段大于 1024。
日期查询
日期值需要使用双引号,并且格式需符合 ISO 8601。支持数学表达式简写:
@timestamp > "2024-01-01"
@timestamp < "now-1d/d"
后者表示时间早于一天前的午夜。
布尔值查询
直接使用 true 或 false(不区分大小写):
is_bot:true
比较运算符
KQL 支持对数值、日期和关键字类型字段使用比较运算符:
>大于<小于>=大于等于<=小于等于
示例:
bytes >= 2048
response_time < 500
逻辑运算符
KQL 使用英文单词 and、or、not(大小写均可)来组合查询条件,并支持括号 () 显式控制优先级。如果不使用括号,not 的优先级最高,and 次之,or 最低。
与(and)
status:200 and extension:php
返回 status 为 200 且 extension 为 php 的文档。
或(or)
status:400 or status:500
非(not)
not status:200
排除 status 为 200 的文档。not 也可以放在字段查询前,但更推荐放在最前面。
组合示例
(status:400 or status:500) and not user:"John Doe"
范围查询
除了比较运算符,KQL 还提供闭区间和开区间的范围查询,适用于数字、日期及 IP 地址字段。
- 闭区间
[ ]:包含边界值bytes:[1000 TO 2000] - 开区间
{ }:不包含边界值bytes:{1000 TO 2000} - 混合区间:一边包含、一边不包含
bytes:[1000 TO 2000}
范围查询中 TO 必须大写,且值两侧不用加引号,除非值本身包含空格(如日期)。例如日期范围:
@timestamp:["2024-06-01" TO "2024-06-30"]
存在性查询
如果只关心某个字段是否存在于文档中,可以使用 * 操作符,即字段存在且不为空。
error_message:*
返回所有含有 error_message 字段的文档。
若字段值为空或不存在,可以用 not 结合:
not error_message:*
注意:KQL 没有类似 exists 的显式函数(新版 ES 有 exists 查询,但在 KQL 中直接使用 * 即可)。
特殊字符的转义
当搜索的值中包含 KQL 保留字符时,需要使用反斜杠 \ 进行转义。也需要转义的字符包括:
( ) " : * \ ? [ ] { }
示例:查找 user_agent 中包含字面量 "Mozilla/5.0 (compatible" 的文档:
user_agent:"Mozilla/5.0 \(compatible"
注意:双引号内部的 \ 和 " 也需要转义。
嵌套字段查询
对于 Elasticsearch 中的嵌套对象(nested 类型),正常 KQL 语法无法直接访问内层属性。KQL 不支持原生的嵌套查询,但可以通过切换到 Lucene 语法或使用 ES|QL 来处理。在 KQL 环境中,若字段是 object 类型(非 nested),可以直接用点号访问:
user.name:"John"
如果文档中 user 是 object 类型,上述语句有效。
多值字段匹配
如果一个字段包含数组(如 tags: ["api", "production"]),KQL 的等于匹配会返回任意一个元素满足条件的文档。
tags:api
只要 tags 数组中存在 “api” 值即可命中。
模糊查询与正则表达式
KQL 不直接支持模糊查询(如 ~)或正则表达式。这类高级匹配需要切换到 Lucene 语法或使用 Elasticsearch 的 Query DSL。对于日常分析,通配符已能满足大部分需求。
实战示例
| 场景 | KQL 语句 |
|---|---|
| 查找今日所有错误日志 | level:ERROR and @timestamp > "now/d" |
| 排除来自测试用户的请求 | not user:"test_user" |
| 响应时间在 200-500ms 之间,且状态码为 200 | response_time:[200 TO 500] and status:200 |
| 搜索路径中包含 “admin” 的请求 | request_path:*admin* |
| 找出所有来自 Chrome 浏览器的请求 | user_agent:"Chrome" (或用通配 user_agent:*Chrome*) |
KQL 的局限性
- 不支持正则表达式和模糊搜索(Levenshtein 距离)。
- 不能在单个
or表达式中对不同字段使用相同的值精简写法(如status:(200 or 400)无效),需分开书写。 - 对嵌套类型的原生支持较弱。
- 查询字符串前后的空格会被自动裁剪,但引号内的空格保留。
当遇到这些场景时,可临时切换至 Lucene 语法或使用 ES|QL 的管道式查询。
最佳实践
- 善用 Kibana 的字段提示:键入字段名时自动补全字段,输入值时会显示可选值列表,极大提升效率。
- 先用自由文本快速探索,再精确字段限定:先看看数据长什么样,然后逐步添加
message:error等字段约束。 - 处理日志或文本时,优先使用通配符代替精确短语:除非你确信日志格式一成不变。
- 保存常用搜索为“Saved Query”:点击搜索栏右侧的软盘图标,方便重复使用。
- 密切关注时间范围:KQL 本身不限制时间,但你选择的 time picker 范围会隐式地过滤结果,务必确认右上角的时间窗口。
掌握以上 KQL 语法,你就能高效地在 Kibana 中探索、过滤和诊断海量数据了。