Lucene查询语法
# Lucene 查询语法
Lucene 查询语法是 Elasticsearch 的底层查询语言,Kibana 的 Lucene 模式和 ES 的 query_string 查询都基于此语法。
# 语法概览
Lucene 查询语法分为两大类:
| 查询类型 | 语法 | 说明 |
|---|---|---|
| Term 查询 | field: value | 精准匹配,不分词 |
| Phrase 查询 | field: "hello world" | 短语匹配,按完整顺序匹配 |
| 通配符查询 | field: hel*o | * 匹配任意字符,? 匹配单个字符 |
| 模糊查询 | field: hello~ | 基于编辑距离的模糊匹配 |
| 范围查询 | field:[1 TO 10] | 数值/日期范围 |
| 布尔查询 | AND / OR / NOT | 逻辑组合 |
| 正则查询 | field:/regex/ | 正则表达式匹配 |
# 基础语法
# Term 查询(词条匹配)
不分词,精确匹配整个字段值:
status: 200
service: user-service
2
注意:Term 查询不会对搜索词分词。
service: user-service不会匹配user或service。
# Phrase 查询(短语匹配)
用双引号包裹,按完整顺序匹配:
message: "connection timeout"
- 匹配:
"connection timeout occurred" - 不匹配:
"timeout connection"(顺序不对) - 不匹配:
"connection reset timeout"(中间有其他词)
# 短语邻近度
~ 后跟数字,表示允许的词间距:
message: "connection timeout"~3
表示 connection 和 timeout 之间最多允许 3 个词,匹配如 "connection was reset due to timeout"。
# 通配符查询
| 通配符 | 含义 | 示例 |
|---|---|---|
* | 匹配 0 个或多个字符 | uri: *ehome* |
? | 匹配 1 个字符 | uri: vnet-vpaas-?edia |
# 匹配以 ehome 开头的 URL
uri: ehome*
# 匹配任意位置包含 ehome 的 URL
uri: *ehome*
# 匹配单个字符差异
service: user-?ervice
2
3
4
5
6
7
8
性能提示:以
*开头的通配符查询性能较差,ES 需要扫描所有词项。尽量避免*xxx形式。
# 模糊查询
~ 表示基于**编辑距离(Levenshtein Distance)**的模糊匹配:
# 默认允许 2 个字符差异
message: error~
# 指定编辑距离为 1
message: error~1
2
3
4
5
| 查询 | 编辑距离 | 匹配示例 |
|---|---|---|
error~ | 2 | error, errors, terror, mirror |
error~1 | 1 | error, errors |
error~0 | 0 | error(等同 Term 查询) |
编辑距离:将一个词变成另一个词所需的最少操作数(插入、删除、替换)。
# 范围查询
# 闭区间 [ ]
# 数值范围(包含边界)
response.time:[100 TO 500]
# 日期范围
@timestamp:["2026-07-31T00:00:00" TO "2026-07-31T23:59:59"]
2
3
4
5
# 开区间 { }
# 不包含边界
response.time:{100 TO 500}
# 混合使用
response.time:[100 TO 500}
2
3
4
5
# 开放范围
# 大于等于 100
response.time:[100 TO *]
# 小于 500
response.time:[* TO 500]
2
3
4
5
# 日期数学
ES 支持日期数学表达式:
@timestamp:["now-1h" TO "now"]
@timestamp:["now-7d" TO "now"]
@timestamp:["now/d" TO "now"] # 今天 0 点到现在
@timestamp:["now-1d/d" TO "now-1d/d"] # 昨天 0 点到昨天结束
2
3
4
| 表达式 | 含义 |
|---|---|
now | 当前时间 |
now-1h | 1 小时前 |
now-1d | 1 天前 |
now-7d | 7 天前 |
now/d | 今天 0 点(向下取整到天) |
now+1d/d | 明天 0 点 |
# 布尔查询
# 运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
AND | 同时满足 | status:200 AND service:user |
OR | 满足其一 | status:200 OR status:201 |
NOT | 排除 | status:200 NOT service:user |
+ | 必须包含 | +status:200 +service:user |
- | 必须排除 | +status:200 -service:user |
注意:Lucene 中
AND、OR、NOT必须大写,小写会被当作普通词项。
# 组合查询
# 括号控制优先级
(status:200 OR status:201) AND service:user-service
# + 和 - 简写
+status:200 -service:order-service
2
3
4
5
# 默认运算符
未指定运算符时,默认为 OR:
# 以下两种写法等价
status:200 status:201
status:200 OR status:201
2
3
可通过 ES 的 default_operator 参数修改为 AND。
# 字段存在性
# 字段存在(有值)
_exists_:uri
# 字段不存在
_missing_:uri
2
3
4
5
注意:ES 6.x+ 中
_exists_和_missing_已废弃,改用:# ES 6.x+ 写法 uri:* # 字段存在 NOT uri:* # 字段不存在1
2
3
# 正则查询
用 / 包裹正则表达式:
# 匹配以 vnet 开头的服务名
service:/vnet-.*/
# 匹配数字结尾
uri:/.*[0-9]+$/
2
3
4
5
限制:Lucene 正则不支持
^和$锚定符,默认全匹配。不支持反向引用和非贪婪量词。
# 转义特殊字符
以下字符在 Lucene 中有特殊含义,需用 \ 转义:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
示例:
# 转义 URL 中的特殊字符
uri: "https\:\/\/example\.com\/api"
# 转义括号
message: "error\(timeout\)"
2
3
4
5
# 分词与匹配
# text 字段 vs keyword 字段
| 字段类型 | 查询行为 | 示例 |
|---|---|---|
text | 搜索词会被分词,分别匹配 | message: connection timeout 匹配包含 connection 或 timeout 的文档 |
keyword | 搜索词不分词,整体匹配 | uri.keyword: "http://example.com" 精准匹配完整 URL |
# 分词器影响
text 字段经过分词器处理后,查询时也会分词:
# 假设 message 是 text 类型,内容为 "Connection Timeout Error"
message: "connection timeout"
# 分词后匹配 "connection" 和 "timeout",能命中
message: "Connection Timeout"
# 大小写不敏感(取决于分词器),能命中
message: "connectiontimeout"
# 不会被分词为两个词,不命中
2
3
4
5
6
7
8
9
# 完整示例
# 示例一:查找错误日志
# 查找 500 错误且包含 timeout 的日志
status:500 AND message:*timeout*
# 查找非 200 的响应
NOT status:200
# 查找 4xx 或 5xx 错误
status:[400 TO 499] OR status:[500 TO 599]
2
3
4
5
6
7
8
# 示例二:按时间范围和服务名查询
# 查找最近 1 小时 user-service 的日志
@timestamp:["now-1h" TO "now"] AND service:user-service
2
# 示例三:排除特定路径
# 查找所有日志但排除健康检查
NOT uri:*health*
2
# 示例四:多字段组合查询
# user-service 的 500 错误,排除 /api/health 路径
+service:user-service +status:500 -uri:*health*
2
# 示例五:模糊匹配 + 范围
# 响应时间大于 500ms 且消息类似 "timeout"
response.time:[500 TO *] AND message:timeout~2
2
# KQL vs Lucene 对比
| 特性 | KQL | Lucene |
|---|---|---|
| 字段匹配 | field: value | field: value |
| 多值 OR | field: ("a", "b") | field:(a OR b) |
| 逻辑运算 | and / or / not(不区分大小写) | AND / OR / NOT(必须大写) |
| 范围查询 | field: [1 TO 10] | field:[1 TO 10] |
| 嵌套查询 | 支持嵌套对象 | 不支持 |
| 字段存在 | field: * | _exists_:field(旧)/ field:*(新) |
| 默认运算符 | OR | OR |
| 可读性 | 更高 | 较低 |
| 适用场景 | Kibana 查询栏 | query_string DSL / Kibana Lucene 模式 |
建议:在 Kibana 中优先使用 KQL,语法更友好;在 ES DSL 的
query_string中使用 Lucene 语法。
# 在 ES DSL 中使用
Lucene 语法通过 query_string 在 ES DSL 中使用:
GET /_search
{
"query": {
"query_string": {
"query": "status:200 AND service:user-service",
"default_field": "message"
}
}
}
2
3
4
5
6
7
8
9
# 常用参数
| 参数 | 说明 | 默认值 |
|---|---|---|
query | Lucene 查询语句 | - |
default_field | 未指定字段时的默认搜索字段 | *(所有字段) |
default_operator | 默认运算符 | OR |
allow_leading_wildcard | 是否允许 * 开头的通配符 | true |
analyze_wildcard | 是否对通配符查询分词 | false |
minimum_should_match | OR 条件最少匹配数 | 1 |
# 示例
GET /_search
{
"query": {
"query_string": {
"query": "(status:200 OR status:201) AND service:user-service",
"default_operator": "AND"
}
},
"size": 10,
"sort": [
{ "@timestamp": "desc" }
]
}
2
3
4
5
6
7
8
9
10
11
12
13