Query DSL(Domain Specific Language)是Elasticsearch提供的基于JSON的查询语言,用于构建复杂的搜索查询。它分为两大类:叶子查询(Leaf Query)和复合查询(Compound Query)。
| 特性 | 查询上下文(Query Context) | 过滤上下文(Filter Context) |
|---|---|---|
| 作用 | 计算相关性评分 | 判断是否匹配(是/否) |
| 性能 | 较慢,需要计算_score | 更快,可以缓存 |
| 使用场景 | 全文搜索、相关性排序 | 精确匹配、范围过滤 |
| 示例 | 搜索"手机"相关商品 | 价格在1000-5000之间 |
最常用的全文搜索查询,会对查询文本进行分词。
# 基础match查询
GET /products/_search
{
"query": {
"match": {
"name": "苹果手机"
}
}
}
# 指定操作符(默认OR)
GET /products/_search
{
"query": {
"match": {
"name": {
"query": "苹果手机",
"operator": "and" # 必须同时包含"苹果"和"手机"
}
}
}
}
# 设置最小匹配度
GET /products/_search
{
"query": {
"match": {
"description": {
"query": "轻薄 便携 高性能 长续航",
"minimum_should_match": "75%" # 至少匹配3个词
}
}
}
}
短语匹配,要求词条顺序一致。
# 精确短语匹配
GET /products/_search
{
"query": {
"match_phrase": {
"description": "iPhone 15 Pro"
}
}
}
# 允许词条间有间隔(slop)
GET /products/_search
{
"query": {
"match_phrase": {
"description": {
"query": "iPhone Pro",
"slop": 2 # 允许中间有最多2个词
}
}
}
}
在多个字段上执行match查询。
# 多字段搜索
GET /products/_search
{
"query": {
"multi_match": {
"query": "iPhone",
"fields": ["name", "description", "brand"]
}
}
}
# 字段权重提升
GET /products/_search
{
"query": {
"multi_match": {
"query": "手机",
"fields": ["name^3", "description", "category^2"],
"type": "best_fields"
}
}
}
# 不同的匹配类型
GET /products/_search
{
"query": {
"multi_match": {
"query": "苹果手机",
"fields": ["name", "description"],
"type": "cross_fields", # 跨字段匹配
"operator": "and"
}
}
}
精确匹配,不分词,用于keyword、数字、日期等字段。
# 精确匹配品牌
GET /products/_search
{
"query": {
"term": {
"brand.keyword": "Apple"
}
}
}
# 精确匹配价格
GET /products/_search
{
"query": {
"term": {
"price": 7999
}
}
}
# 带权重的term查询
GET /products/_search
{
"query": {
"term": {
"category.keyword": {
"value": "手机",
"boost": 2.0
}
}
}
}
匹配多个精确值(OR关系)。
# 匹配多个品牌
GET /products/_search
{
"query": {
"terms": {
"brand.keyword": ["Apple", "Samsung", "Huawei"]
}
}
}
# 匹配多个价格
GET /products/_search
{
"query": {
"terms": {
"price": [5999, 7999, 9999]
}
}
}
范围查询,用于数字、日期等字段。
# 价格范围查询
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 5000, # 大于等于
"lte": 10000 # 小于等于
}
}
}
}
# 日期范围查询
GET /products/_search
{
"query": {
"range": {
"release_date": {
"gte": "2023-01-01",
"lt": "2024-01-01",
"format": "yyyy-MM-dd"
}
}
}
}
# 相对时间查询
GET /logs/_search
{
"query": {
"range": {
"timestamp": {
"gte": "now-7d/d", # 最近7天
"lt": "now/d"
}
}
}
}
查询字段存在的文档。
# 查询有description字段的文档
GET /products/_search
{
"query": {
"exists": {
"field": "description"
}
}
}
# 查询没有description字段的文档
GET /products/_search
{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "description"
}
}
}
}
}
Bool查询是最重要的复合查询,可以组合多个查询条件。
| 子句 | 说明 | 影响评分 |
|---|---|---|
| must | 必须匹配,相当于AND | 是 |
| should | 应该匹配,相当于OR | 是 |
| must_not | 必须不匹配,相当于NOT | 否(过滤上下文) |
| filter | 必须匹配,但不计算评分 | 否(过滤上下文) |
# 复杂bool查询示例
GET /products/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "手机"
}
}
],
"filter": [
{
"range": {
"price": {
"gte": 3000,
"lte": 8000
}
}
},
{
"term": {
"status.keyword": "在售"
}
}
],
"should": [
{
"term": {
"brand.keyword": "Apple"
}
},
{
"term": {
"brand.keyword": "Samsung"
}
}
],
"must_not": [
{
"term": {
"category.keyword": "二手"
}
}
],
"minimum_should_match": 1
}
}
}
# 嵌套bool查询
GET /products/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"category": "手机"
}
}
],
"filter": [
{
"bool": {
"should": [
{
"range": {
"price": {
"lte": 3000
}
}
},
{
"term": {
"brand.keyword": "Apple"
}
}
]
}
}
]
}
}
}
# 通配符查询
GET /products/_search
{
"query": {
"wildcard": {
"name.keyword": {
"value": "iPhone*" # *匹配任意字符,?匹配单个字符
}
}
}
}
# 前缀查询
GET /products/_search
{
"query": {
"prefix": {
"name.keyword": "iPhone"
}
}
}
# 模糊查询(容错搜索)
GET /products/_search
{
"query": {
"fuzzy": {
"name": {
"value": "iPone", # 拼写错误
"fuzziness": "AUTO" # 自动计算编辑距离
}
}
}
}
1. Match查询练习
2. Term查询练习
3. Bool查询练习
4. Multi Match练习
5. 高级查询
6. 实战场景
7. 性能对比
8. 调试查询
Q: match和term有什么区别?
A: match用于全文搜索,会对查询文本分词;term用于精确匹配,不分词。match适用于text字段,term适用于keyword、数字、日期等字段。
Q: 什么时候用must,什么时候用filter?
A: 需要相关性评分时用must,只需要过滤数据时用filter。filter性能更好且可以缓存,建议优先使用。
Q: minimum_should_match如何使用?
A: 可以使用数字(至少匹配N个条件)、百分比(至少匹配N%的条件)或组合表达式。例如:"2"表示至少匹配2个,"75%"表示至少匹配75%。
Q: 如何提高查询性能?
A: 1) 使用filter代替must;2) 避免wildcard和regex查询;3) 合理设置分片数量;4) 使用routing减少查询分片;5) 启用查询缓存。