深入学习 ElasticSearch 的搜索(六):搜索语法总结

深入学习 ElasticSearch 的搜索(六):搜索语法总结

前面几篇分别整理了:

  • Query DSL
  • match
  • match_phrase
  • term
  • bool

这一篇做一次总结,把这些查询放到同一张图里理解。

ElasticSearch 搜索最容易混淆的点,通常不是语法本身,而是没有分清:

  • 字段是 text 还是 keyword
  • 查询是否会走 analyzer
  • 条件是用于评分还是用于过滤
  • 查询目标是全文检索还是精确匹配

一、先按字段类型判断

ElasticSearch 搜索之前,先看字段类型。

Mapping 可以理解为索引的字段结构说明书。它决定字段应该如何被索引、如何被搜索。

也就是说,搜索设计的第一步不是写 DSL,而是先判断字段身份:

  • 自然语言内容:通常用 text
  • 结构化精确值:通常用 keyword、数字、日期、布尔等类型

字段身份错了,后面的查询再复杂也很难自然。


1. text 字段

text 字段会分词。

适合:

  • 标题
  • 正文
  • 摘要
  • 评论
  • 描述信息

常用查询:

  • match
  • match_phrase

例如:

json 复制代码
POST article_search/_search
{
  "query": {
    "match": {
      "content": "ElasticSearch 倒排索引"
    }
  }
}

2. keyword 字段

keyword 字段通常不分词。

适合:

  • 分类
  • 状态
  • 标签
  • 用户 ID
  • 订单号
  • 枚举值

常用查询:

  • term
  • terms
  • bool.filter

例如:

json 复制代码
POST article_search/_search
{
  "query": {
    "term": {
      "category": "elasticsearch"
    }
  }
}

3. multi-fields

实际项目中,同一个字段经常既需要全文检索,又需要精确匹配。

这时可以使用 multi-fields:

json 复制代码
PUT article_search_v2
{
  "mappings": {
    "properties": {
      "nickname": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

这样:

  • nickname:用于 matchmatch_phrase
  • nickname.keyword:用于 term、排序、聚合

这也是很多搜索系统里最常见的字段建模方式。


二、match、match_phrase、term 的区别

可以用下面这张表理解。

查询 是否分析查询文本 适合字段 典型用途
match text 全文关键词搜索
match_phrase text 连续短语搜索
term keyword 精确值匹配

一句话记忆:

text 复制代码
match 查词,match_phrase 查短语,term 查精确值。

三、match 怎么用

match 是全文检索入口。

json 复制代码
POST article_search/_search
{
  "query": {
    "match": {
      "content": "ElasticSearch 搜索"
    }
  }
}

适合:

  • 用户输入关键词
  • 搜文章正文
  • 搜标题
  • 搜自然语言文本

关键点:

  • 查询文本会被 analyzer 分析
  • 命中结果会计算 _score
  • 默认比较宽松
  • 可以用 operatorminimum_should_match 控制严格程度

四、match_phrase 怎么用

match_phrase 用于短语查询。

json 复制代码
POST article_search/_search
{
  "query": {
    "match_phrase": {
      "content": "倒排索引"
    }
  }
}

适合:

  • 搜固定表达
  • 搜连续标题
  • 搜日志片段
  • 提高结果精确度

关键点:

  • 查询文本也会被 analyzer 分析
  • 不只看 term 是否出现,还看 position
  • 可以用 slop 放宽距离

五、term 怎么用

term 用于精确词项查询。

json 复制代码
POST article_search/_search
{
  "query": {
    "term": {
      "status": "published"
    }
  }
}

适合:

  • 查状态
  • 查分类
  • 查用户 ID
  • 查枚举值
  • 查精确标签

关键点:

  • 不要用它做普通全文搜索
  • text 字段使用时要特别小心
  • 最常搭配 keyword 字段

六、bool 怎么用

bool 用来组合多个条件。

json 复制代码
POST article_search/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "ElasticSearch"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "status": "published"
          }
        }
      ],
      "should": [
        {
          "match": {
            "title": "ElasticSearch"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "author": "ops"
          }
        }
      ]
    }
  }
}

四个子句的含义:

  • must:必须匹配,并参与评分
  • filter:必须匹配,不参与评分
  • should:最好匹配,通常用于加分
  • must_not:必须不匹配

七、一套常用业务搜索模板

很多后台搜索都可以从这个模板开始:

json 复制代码
POST article_search/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "ElasticSearch"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "status": "published"
          }
        },
        {
          "term": {
            "category": "elasticsearch"
          }
        },
        {
          "range": {
            "created_at": {
              "gte": "2026-04-01",
              "lte": "2026-04-30"
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "created_at": {
        "order": "desc"
      }
    }
  ]
}

这个模板里:

  • from / size 控制分页
  • match 做全文检索
  • term 做精确过滤
  • range 做范围过滤
  • sort 做排序

八、高亮和返回字段控制

业务搜索通常还需要控制返回字段和高亮。

例如只返回标题、分类、创建时间,并对正文命中的关键词做高亮:

json 复制代码
POST article_search/_search
{
  "_source": ["title", "category", "created_at"],
  "query": {
    "match": {
      "content": "ElasticSearch"
    }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}

其中:

  • _source 控制返回哪些原始字段
  • highlight 控制命中片段高亮

如果文档很大,合理控制 _source 可以减少网络传输和客户端处理成本。


九、分页要注意什么

普通分页可以使用 fromsize

json 复制代码
POST article_search/_search
{
  "from": 20,
  "size": 10,
  "query": {
    "match_all": {}
  }
}

它适合浅分页。

如果页数很深,例如翻到几千页,from + size 的成本会明显升高。

深分页场景通常要考虑:

  • search_after
  • PIT
  • 避免无限制跳页

普通后台列表可以先用 from + size,但要限制最大翻页深度。


十、前缀、通配和联想搜索

搜索框输入时,通常有两种模式:

  • 搜索结果页:用户输入完整关键词后搜索
  • 联想建议:用户边输入边出结果

正式搜索结果页更重视排序质量,通常使用:

text 复制代码
multi_match + bool + phrase + boost

联想建议更重视响应速度和前缀匹配,可以考虑:

  • match_bool_prefix
  • search_as_you_type
  • completion suggester
  • edge_ngram

通配符查询如 wildcard 虽然直观,但不要轻易当主查询。

json 复制代码
POST article_search/_search
{
  "query": {
    "wildcard": {
      "author": "*adm*"
    }
  }
}

这类查询在大数据量下可能比较重,而且排序语义也不如全文查询自然。真要大量使用通配搜索,最好从 mapping 层专门设计。


十一、小说分块搜索的字段建模例子

如果是小说分块或内容 chunk 搜索,字段可以按用途拆开。

示例文档:

json 复制代码
{
  "book_id": "book_001",
  "chapter_index": 12,
  "chapter_title": "武当山上",
  "chunk_text": "饭后,张三丰看着郭靖,没有说话。",
  "entity_names": ["张三丰", "郭靖"],
  "start_line": 120,
  "word_count": 86
}

建议的搜索语义:

  • chunk_text:正文全文搜索,用 match / match_phrase
  • chunk_text.keyword:整段完全相等时才用 term
  • entity_names:人名实体精确检索,用 term / terms
  • book_id:书籍过滤,用 term
  • chapter_indexstart_lineword_count:范围过滤,用 range

一个完整查询可以这样写:

json 复制代码
POST article_search/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "chunk_text": "武当"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "book_id": "book_001"
          }
        },
        {
          "terms": {
            "entity_names": ["张三丰", "郭靖"]
          }
        },
        {
          "range": {
            "chapter_index": {
              "gte": 1,
              "lte": 20
            }
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "entity_names": "郭襄"
          }
        }
      ],
      "should": [
        {
          "match_phrase": {
            "chunk_text": {
              "query": "张三丰",
              "boost": 3
            }
          }
        }
      ]
    }
  }
}

这里的重点不是字段名,而是建模思路:

正文走全文,实体走精确,范围走 filter,排序靠 should 和 boost。


十二、排查搜索不准的顺序

如果搜索结果不符合预期,建议按下面顺序排查。


1. 看 mapping

先确认字段类型。

json 复制代码
GET article_search/_mapping

重点看:

  • 字段是不是 text
  • 字段是不是 keyword
  • 字段用了哪个 analyzer
  • 是否配置了 search_analyzer

2. 看 analyzer

_analyze 看文本会被拆成什么。

json 复制代码
POST article_search/_analyze
{
  "field": "content",
  "text": "ElasticSearch 倒排索引"
}

如果分词不符合预期,先解决 analyzer。


3. 看查询类型

确认是不是用错了查询:

  • 全文搜索却用了 term
  • 精确过滤却用了 match
  • 短语搜索却用了普通 match
  • 多条件查询没有用 bool

4. 看 filter 和 score

如果某些过滤条件影响了排序,检查是否把本该放 filter 的条件放进了 must

如果结果太多,考虑:

  • operator: "and"
  • minimum_should_match
  • match_phrase
  • 增加 filter

十三、排查评分:explain 和 profile

如果想知道某篇文档为什么命中、为什么评分高,可以用 _explain

json 复制代码
GET article_search/_explain/1
{
  "query": {
    "match": {
      "content": "ElasticSearch"
    }
  }
}

如果想分析查询执行过程和耗时,可以在搜索请求中开启 profile

json 复制代码
POST article_search/_search
{
  "profile": true,
  "query": {
    "match": {
      "content": "ElasticSearch"
    }
  }
}

这两个工具适合排查问题,不建议在普通业务请求中长期打开。


十四、为什么排序有时看起来不合理

ElasticSearch 默认会根据相关性模型计算 _score,常见默认模型是 BM25。

搜索结果看起来"不合理",通常不是单个 DSL 语法错了,而是这些因素叠加:

  • 字段类型设计错了
  • 应该精确查的字段走了全文搜索
  • 字段权重没有配置
  • 短语优先没有做
  • 过滤条件写进了 must,污染了评分
  • fuzzywildcard 被当成主查询

常见优化方式:

  • 给重要字段更高 boost
  • .keyword 做精确命中加权
  • match_phrase 给完整短语加分
  • 结构化条件放入 filter

十五、最常用的判断口诀

可以按下面方式选择查询:

text 复制代码
搜正文标题:match
搜连续短语:match_phrase
搜分类状态:term
多个条件组合:bool
结构化过滤:bool.filter
排除数据:bool.must_not
提升相关性:bool.should

再结合字段类型:

text 复制代码
text -> match / match_phrase
keyword -> term / terms
number/date -> range / term

十六、一句话总结

ElasticSearch 搜索语法的核心不是背 API,而是先分清查询意图。

最终可以这样理解:

用户输入的自然语言,用 match;需要连续短语,用 match_phrase;结构化精确值,用 term;多个条件组合,用 bool。

只要把字段类型、分词结果、查询类型这三件事对齐,大部分搜索问题都会变得容易排查。


参考链接

相关推荐
码农学院19 分钟前
Elasticsearch构建汽车零配件智能搜索与匹配系统
大数据·elasticsearch·汽车
Elastic 中国社区官方博客17 小时前
不到 5 分钟完成本地部署:Jina embedding 模型现已支持本地部署
大数据·人工智能·elasticsearch·搜索引擎·embedding·jina
二进制流水搬运工17 小时前
入职第一天拉了23个仓库,我写了个脚本解放双手
大数据·elasticsearch·搜索引擎
Elasticsearch18 小时前
在不到一小时内将 Datadog Kubernetes 仪表板迁移到 Elastic Observability
elasticsearch
.柒宇.19 小时前
Elasticsearch 核心概念与系统架构详解
elasticsearch·系统架构
风行無痕21 小时前
单机Elasticsearch 8.19.18安全升级到9.4.3的过程
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客1 天前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
大数据·运维·前端·人工智能·elasticsearch·搜索引擎·全文检索
阿拉雷️1 天前
【搜索实战】Spring Boot 3.3 + AI Agent × Elasticsearch:让AI自动优化搜索策略,查询速度从2秒压到50毫秒
人工智能·spring boot·elasticsearch
阿里云大数据AI技术2 天前
阿里云 ES AI 引擎版:面向 Agent 场景,为亿级租户、千亿规模向量设计的搜索引擎
人工智能·elasticsearch·agent
阿里云大数据AI技术2 天前
FalconSeek 技术解析:阿里云 Elasticsearch 云原生内核如何让查询性能飙升600%
人工智能·elasticsearch