适用场景:Kibana Discover 搜索框,查询技巧
一、基础语法
1.关键词查询(要想关键词不被分词,每个关键词都加上引号)
单关键词: apple
// apple 模糊匹配
// 说明: 模糊匹配包含"apple"的文档,会匹配 apple、apples、pineapple 等
// 示例: 输入 error 会匹配所有包含 error 这个词的日志记录
多关键词(默认 OR): apple phone
// 说明: 匹配包含"apple"或"phone"任意一个的文档,等价于 apple OR phone
// 示例: 输入 手机 平板 会匹配包含手机的文档或包含平板的文档
// 注意: 两个词之间有空格,默认是 OR 关系,不是 AND
精确短语(双引号): "apple phone"
// 说明: 精确匹配完整短语"apple phone",顺序和空格都必须完全一致,不会被分词
// 示例: "hello world" 只匹配完整的"hello world",不匹配 hello new world
// 示例: "辽 HG5788" 精确匹配这个车牌号,不会匹配辽 A HG5788
指定字段: title:apple (冒号前面是索引字段,title/status/carmark是否存在,推荐操作示例:"carmark 辽HG5788",类似查找 "carmark":"辽HG5788")
// 说明: 只在 title 字段中搜索 apple,例如只查找标题中包含 apple 的记录
// 示例: status:200 只查找 status 字段值为 200 的记录
// 示例: carmark:辽HG5788 只查找车牌号 为 辽HG5788 的记录
字段 + 短语: content:"hello world" (content为索引字段)
// 说明: 在 content 字段中精确搜索完整短语"hello world"
// 示例: message:"error occurred" 在 message 字段中查找完整短语"error occurred"
// 示例: title:"智能手机" 在 title 字段中查找完整短语"智能手机"
多字段查询: (title:apple OR content:apple) (冒号前面是索引字段)
// 说明: 在 title 字段或 content 字段中任意一个包含 apple 的文档都会被匹配
// 示例: (name:"张三" OR nickname:"张三") 查找姓名或昵称包含张三的记录
// 示例: (message:error OR stack_trace:error) 在消息或堆栈轨迹中查找 error
2.逻辑操作符(必须大写)
AND(与): apple AND phone 、 title:apple AND status:1
// 说明: 必须同时包含 apple 和 phone 两个词才会被匹配
// 示例: title:apple AND status:1 表示标题包含 apple 且状态为 1 的记录
// 示例: message:error AND level:critical 表示错误消息且级别为严重
// 示例: user_id:123 AND status:active 用户 123 的活跃状态记录
OR(或): apple OR phone 、 status:200 OR status:500
// 说明: 只要包含 apple 或 phone 中任意一个就会被匹配
// 示例: status:200 OR status:500 表示状态是 200 或 500 的记录
// 示例: type:admin OR type:superuser 表示管理员或超级用户
// 示例: level:ERROR OR level:WARN 表示错误或警告级别的日志
NOT(非): apple NOT phone 、 status:200 NOT tag:test
// 说明: 包含 apple 但不包含 phone 的文档,用于排除某些内容
// 示例: status:200 NOT tag:test 表示状态 200 但标签不是 test 的记录
// 示例: product:手机 NOT brand:苹果 表示手机但不是苹果品牌
// 示例: message:error NOT handled 表示错误消息但未被处理的记录
简写符号: +apple +phone(等价 AND)、 +apple -phone(包含 A 排除 B)
// 说明: + 表示必须包含,- 表示必须排除
// +apple +phone 等价于 apple AND phone
// +apple -phone 表示必须有 apple 且不能有 phone
// 示例: +error -warning 表示有错误但没有警告的日志
// 示例: +status:200 -tag:deprecated 状态 200 且不是废弃标签
3.括号分组
基础分组: apple OR (phone AND tablet)
// 说明: 先计算括号内的 phone AND tablet,再与 apple 进行 OR 运算
// 匹配: 包含 apple,或同时包含 phone 和 tablet 的文档
// 示例: A OR (B AND C) = A 或 (B 且 C)
// 示例: error OR (warning AND critical) 错误日志,或严重警告日志
字段分组: status:(200 OR 201 OR 202)
// 说明: 等价于 status:200 OR status:201 OR status:202
// 匹配: status 字段值为 200、201 或 202 的任意一个
// 示例: level:(ERROR OR WARN OR INFO) 匹配任意日志级别
// 示例: type:(admin OR user OR guest) 匹配任意用户类型
复杂组合: (status:200 AND (title:"手机" OR title:"平板")) NOT tag:"二手"
// 执行顺序:
// 1. 先算最内层:title:"手机" OR title:"平板"
// 2. 再算 AND:status:200 且满足第 1 步
// 3. 最后算 NOT:排除 tag:"二手" 的记录
// 示例: 查找状态正常且是手机或平板,但排除二手商品
// 示例: (level:ERROR AND (service:api OR service:db)) NOT env:test 生产环境的 API 或数据库错误
二、高级查询
1.通配符
? 匹配单个字符: test? → tests/testa/test1
// 说明: ? 代表任意单个字符,test? 可以匹配 tests、testa、test1、testX 等
// 注意: 必须正好 5 个字符,test 不匹配,test?? 才匹配 6 个字符
// 示例: user? 可以匹配 user1、userA、user_ 等单个字符结尾
*** 匹配 0 或多个字符:** app* → apple/application/app
// 说明: * 代表任意多个字符(包括 0 个),app* 可以匹配 app、apple、application、apply 等
// 示例: user* 可以匹配 user、users、username、user123
// 示例: DD260316000355* 匹配以 DD260316000355 开头的任何运单号
字段 + 通配符: user_id:u*er → user/uber/u123er
// 说明: 在 user_id 字段中搜索,u 开头 er 结尾的所有值
// 匹配: user、uber、u123er、uXXXer 等
// 示例: trace_id:abc*xyz 匹配 abc 开头 xyz 结尾的 trace ID
⚠️ 注意: *开头的通配符(ing)性能差,慎用
// 前缀通配符(如 abc)性能好,因为可以使用索引
// 后缀通配符(如 *ing)需要扫描所有数据,性能很差
// 建议: 尽量使用 abc* 而不是 *abc 或 *abc*
2.模糊查询(容错拼写)
基础模糊: apple~(编辑距离≤2)
// 说明: ~ 表示允许拼写错误,apple~ 可以匹配 aple、appl、apples、pple 等
// 编辑距离: 将一个词变成另一个词需要的最少操作次数(增删改)
// 默认: 编辑距离为 2,即最多允许 2 个字母的差异
// 示例: aple~ 可以匹配正确的 apple
// 示例: 辽 HG5788~ 即使车牌号有点小错误也能匹配
指定相似度: apple~0.9(0~1,越大越严格)
// 说明: 0.9 表示相似度必须≥90%,数值越接近 1 要求越严格
// apple~0.5 可以匹配更多差异较大的词
// apple~1.0 几乎要求完全匹配(等价于精确查询)
// 示例: name:张三~0.8 允许名字有一定误差
// 示例: product:iphone~0.9 容错拼写错误
字段 + 模糊: title:aple~1 → 拼错也能匹配 apple
// 说明: 即使输入错误的 aple,也能找到 title 字段中包含 apple 的记录
// 适用: 用户输入可能有拼写错误的场景
// 示例: message:errro~1 即使 error 拼错了也能找到
// 示例: waybill:DD26031600035~ 运单号输错一位也能匹配
3.近似查询(短语顺序灵活)
语法: "短语"~允许间隔词数
// 说明: 近似查询允许短语中的词之间有其他词插入,但顺序必须一致
示例: "apple phone"~1 → 匹配"apple new phone"、"phone and apple"
// 说明: "apple phone"~1 表示 apple 和 phone 之间最多间隔 1 个词
// 匹配: "apple phone"(0 间隔)、"apple new phone"(1 间隔)
// 不匹配: "apple very new phone"(间隔 2 个词,超过限制)
// 示例: "error occurred"~2 可以匹配"error has occurred"或"error suddenly occurred"
实战: "辽 HG5788"~2 → 匹配车牌中间有少量干扰词
// 匹配: "辽 HG5788"、"辽 A HG5788"、"辽·HG5788"
// 适用: 文本中有少量标点或语气词干扰的场景
// 示例: "DD260316000355"~1 运单号中间可能有短横线或其他分隔符
4.范围查询
数字范围:
price:[100 TO 200] → 100≤price≤200(包含边界)
// 说明: 方括号 [] 表示包含边界值,匹配 100、150、200 等
// 示例: age:[18 TO 60] 匹配 18 到 60 岁(包含 18 和 60)
// 示例: score:[60 TO 100] 匹配及格到满分的成绩
price:{100 TO 200} → 100<price<200(不包含边界)
// 说明: 花括号 {} 表示不包含边界值,匹配 101、150、199 等,不匹配 100 和 200
// 示例: age:{18 TO 60} 匹配 19-59 岁(不包含 18 和 60)
price:[100 TO *] → price≥100
// 说明: * 表示无穷大,匹配大于等于 100 的所有值
// 示例: salary:[5000 TO *] 月薪 5000 及以上
price:[* TO 200] → price≤200
// 说明: 匹配小于等于 200 的所有值
// 示例: discount:[* TO 50] 折扣不超过 50%
日期范围:
@timestamp:[2024-01-01T00:00:00 TO 2024-01-02T00:00:00]
// 说明: 查询 2024 年 1 月 1 日全天的数据(包含起止时间点)
// 格式: ISO 8601 时间格式
@timestamp:[now-1h TO now] → 最近 1 小时
// 说明: now 表示当前时间,now-1h 表示 1 小时前
// 动态时间范围,常用于查询最近的日志
// 示例: @timestamp:[now-24h TO now] 最近 24 小时
// 示例: @timestamp:[now-7d TO now] 最近 7 天
组合示例: status:200 AND price:[50 TO 200] AND @timestamp:[now-24h TO now]
// 说明: 查询最近 24 小时内,状态为 200 且价格在 50-200 之间的记录
// 示例: level:ERROR AND @timestamp:[now-1h TO now] AND service:api 最近 1 小时 API 服务的错误日志
5.权重查询(影响排序)
语法: 关键词^权重值
// 说明: ^ 用于提高某个关键词的重要性,影响搜索结果的相关性评分
// 作用: 权重越高,匹配该词的文档在结果中排名越靠前
示例: apple^2 phone → apple 匹配权重是 phone 的 2 倍
// 说明: 同时包含 apple 和 phone 的文档中,apple 的贡献更大
// 效果: 包含 apple 的文档会比只包含 phone 的文档排名更高
// 示例: error^3 warning^2 info 错误最重要,警告次之,信息最不重要
实战: "DD260316000355"^3 OR "辽 HG5788"^2 OR waybillGenerateBy
// 说明: 运单号"DD260316000355"最重要(权重 3),其次是车牌"辽 HG5788"(权重 2)
// waybillGenerateBy 权重默认为 1
// 适用: 多个搜索词重要性不同的场景
// 示例: title:"手机"^3 description:"手机"^1 标题中含手机的优先级更高
三、特殊用法
1.字段存在性查询
字段存在: _exists_:title | _exists_:resultId
// 说明: 查询 title 字段或 resultId 字段不为空的文档
// 等价于: SQL 中的 IS NOT NULL
// 示例: _exists_:error_msg 查找所有包含错误信息的日志
// 示例: _exists_:user_id 查找有用户 ID 的记录(排除匿名用户)
字段不存在: NOT _exists_:error_msg
// 说明: 查询 error_msg 字段为空或不存在的文档
// 等价于: SQL 中的 IS NULL
// 示例: 筛选没有报错的正常记录
// 示例: NOT _exists_:exception 查找没有异常的正常请求
2.转义特殊字符
需转义字符: + - && || ! ( ) { } [ ] ^ " ~ * ? : \
// 说明: 这些字符在 Lucene 中有特殊含义,如果要搜索字符本身,需要用\转义
示例: 搜索 (1+1):2 → \(1\+1\)\:2
// 说明: (、)、+、: 都是特殊字符,必须逐个转义
// 原因: 否则会被解析为分组或操作符
// 示例: 搜索 a+b=c → a\+b\=c
示例: 搜索含*的产品 → product:"iPhone \*"
// 说明: * 是通配符,要搜索实际的星号字符需要转义
// 应用场景: 搜索型号中的星号、数学公式等
// 示例: 搜索 C++ → C\+\+
// 示例: 搜索 100% → 100\%
3.默认字段查询
不写字段名,在默认字段(_all 或 message)中搜索
// 说明: ES 会将多个字段的值合并到_all 字段(ES 7.x 后需配置)
// 或在 Kibana 中设置了默认字段(如 message)
示例: "辽 HG5788" | DD260316000355
// 说明: 直接在所有默认字段中搜索,不用指定具体字段
// 适用: 不确定关键词在哪个字段,或想全局搜索时
// 示例: 直接输入 error 会在所有字段中搜索 error
等价于: _all:"辽 HG5788"
// 说明: 显式指定在_all 字段中搜索
// 注意: ES 7.0+ 版本_all 字段默认禁用,需在 mapping 中手动开启
// 替代方案: 在 Kibana 设置中指定默认查询字段
四、实战示例
场景 1:日志排查(车牌 + 运单号)
同文档查询: "辽 HG5788" AND "DD260316000355"
// 说明: 查找同一篇日志中同时包含车牌和运单号的记录
// 适用: 单次请求同时记录了多个关键信息的场景
// 示例: 某次运输请求的日志同时记录了车辆和运单信息
跨文档查询: "辽 HG5788" OR "DD260316000355"
// 说明: 查找包含车牌或运单号的任意日志,可能在不同文档中
// 适用: 追踪分散在不同日志条目中的相关信息
// 示例: 同一订单的不同处理阶段记录了不同关键信息
加时间范围: ("辽 HG5788" OR "DD260316000355") AND @timestamp:[now-1h TO now]
// 说明: 限定在最近 1 小时内,避免历史数据干扰
// 推荐: 总是加上时间范围提高查询效率和准确性
// 示例: (trace_id:xyz-123 OR order_id:12345) AND @timestamp:[now-24h TO now]
场景 2:状态筛选 + 关键词
状态 200 且含 error: status:200 AND message:error
// 说明: 虽然 HTTP 状态码是 200(成功),但消息体中包含 error 关键词
// 适用: 排查表面成功但实际有问题的异常情况
// 示例: 接口返回成功但有错误提示信息
状态 200 或 500 且含用户: (status:200 OR status:500) AND user_id:12345
// 说明: 查询特定用户(user_id=12345)的成功或失败请求
// 执行顺序: 先括号内 OR,再与 user_id 进行 AND
// 示例: 排查某个用户的所有请求(无论成功失败)
场景 3:模糊匹配运单号
运单号带前后缀: *DD260316000355*
// 说明: 前后都有*,匹配任何包含该运单号的文本
// 匹配: WAYBILL-DD260316000355-001、SO-DD260316000355 等
// 缺点: 性能较差,因为需要全表扫描
// 适用: 不确定运单号位置时的应急方案
只匹配后缀(性能更好): DD260316000355*
// 说明: 只匹配以 DD260316000355 开头的文本
// 匹配: DD260316000355、DD260316000355-001 等
// 优点: 可以利用索引,性能更好
// 建议: 尽量使用后缀通配符,避免前缀通配符
场景 4:多条件组合查询
查最近 1 小时,状态 200,含手机或平板,排除测试:
(status:200 AND (title:"手机" OR title:"平板") AND NOT tag:"测试" AND @timestamp:[now-1h TO now])
// 分解执行逻辑:
// 1. time: @timestamp:[now-1h TO now] → 最近 1 小时
// 2. status: status:200 → 成功状态
// 3. title: title:"手机" OR title:"平板" → 标题包含任一关键词
// 4. exclude: NOT tag:"测试" → 排除测试数据
// 最终: 同时满足以上所有条件的记录
// 技巧: 复杂查询一定要用括号明确优先级
// 示例: (level:ERROR AND service:api AND @timestamp:[now-24h TO now]) NOT env:test 最近 24 小时生产环境 API 的错误日志
五、常见坑与最佳实践
常见错误
-
逻辑符小写:
apple and phone❌ →apple AND phone✅
// 逻辑操作符必须大写,否则会被当成普通关键词 -
空格导致隐式 OR:
title:苹果 手机❌ →title:"苹果 手机"✅
// 空格会被当成 OR,精确短语必须加引号 -
text 字段查精确值:
status:200❌ →status.keyword:200✅
// text 类型字段会被分词,精确值查询要用.keyword 后缀 -
前缀通配符性能差:
*123❌ →123*✅
// 前缀*无法使用索引,性能极差,尽量避免
最佳实践
-
精确值用.keyword:
user_id.keyword:12345|status.keyword:200
// 避免分词,精确匹配整个值 -
复杂查询加括号:
(status:200 OR 201) AND (title:"A" OR "B")
// 明确优先级,避免歧义 -
时间范围配合关键词:
"辽 HG5788" AND @timestamp:[now-24h TO now]
// 减少搜索范围,提高效率 -
通配符用后缀:
trace_id:abc*✅ |trace_id:*abc❌
// 后缀通配符可以利用索引 -
日志关联用 Trace ID:
trace_id:xyz-123✅ 一次性查出同一请求所有日志
// 分布式链路追踪的最佳实践
六、快速对照表
| 需求 | Lucene 语法 | 说明 |
|---|---|---|
| 同时包含 | A AND B | 逻辑与,必须同时满足 |
| 包含任意 | A OR B | 逻辑或,满足其一即可 |
| 排除 | A NOT B | 逻辑非,满足 A 但不满足 B |
| 必须包含 | +A | 等价 must,必须包含 A |
| 必须排除 | -A | 等价 must_not,必须不包含 A |
| 精确短语 | "A B" | 完整短语,顺序不变 |
| 模糊匹配 | A~ | 容错拼写,允许一定误差 |
| 近似短语 | "A B"~2 | 允许间隔 2 个词 |
| 单字符通配 | A?C | 匹配 ABC/A1C(正好 1 个字符) |
| 多字符通配 | A*C | 匹配 ABC/A123C(0 或多个字符) |
| 范围查询 | [1 TO 10] | 包含边界,1≤x≤10 |
| 字段存在 | exists:field | 字段不为空 |
| 权重排序 | A^2 | A 权重翻倍,影响排序 |
七、Kibana 使用提示
-
切换语法: 搜索框左上角点击 KQL/Lucene 切换
// KQL 更简单,Lucene 更强大 -
执行查询: 输入后按 Enter 或点击搜索按钮
// Shift+Enter 可以换行(多行查询时) -
查看历史: 点击搜索框左侧时钟图标
// 快速复用之前的查询语句 -
字段补全: 输入字段名时有自动提示
// 帮助快速输入正确的字段名 -
时间筛选: 右上角时间选择器独立于搜索语法
// 时间选择器是额外的过滤条件
八、跨文档关联查询方案
问题:关键词分散在不同文档,能否一起查出?
直接 AND 查询 ❌ 不能,ES 要求所有词在同一文档
// ES 的 AND 查询要求所有关键词出现在同一个文档中
解决方案
方案 1:Trace ID 关联(推荐)
开发侧:所有日志打印同一 trace_id
查询:trace_id:"xyz-123" → 一次性查出同一请求所有日志
// 优点: 精确、高效、无噪音
// 实施: 在全链路所有服务中透传同一个请求 ID
方案 2:OR 查询 + 时间窗口
查询:("辽 HG5788" OR "DD260316000355") AND @timestamp:[now-1h TO now]
注意:可能混入无关日志,需人工筛选
// 优点: 不需要代码改造
// 缺点: 可能召回不相关的日志
方案 3:Kibana 上下文视图
操作:找到一条日志 → 点击行首箭头 → 查看前后相邻日志
适用:快速查看某条日志的执行上下文
// 优点: 直观方便
// 缺点: 只能查看相邻日志,不适合跨时间段查询
方案 4:业务字段 + 时间组合
查询:user_id:"123" AND @timestamp:[T1-30s TO T1+30s]
适用:无法加 Trace ID 时的应急方案
// 优点: 基于现有业务字段
// 缺点: 时间窗口难确定,可能有遗漏
核心结论
- 同一文档多关键词: 用 AND
- 跨文档关联查询: 用 Trace ID 或 OR+ 时间窗口
- 日志分析最佳实践: 全链路透传唯一请求 ID
文档版本: v2.0(详细注释版) | 适用: ES 7.x/8.x, Kibana 7.x/8.x
更新时间: 2024-01-XX