深入学习 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。

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


参考链接

相关推荐
Volunteer Technology8 小时前
ES相关度评分算法
大数据·算法·elasticsearch
独隅8 小时前
it+云原生:GitOps实践指南-K8s配置版本管理
git·elasticsearch·云原生
海兰8 小时前
将 Cursor 连接到生产日志:通过 Elastic MCP 服务器
运维·服务器·elasticsearch
Elastic 中国社区官方博客8 小时前
2026 年金融服务可观测性现状:从实施到业务影响
大数据·运维·人工智能·elasticsearch·搜索引擎·金融·自动化
Cc不爱吃洋葱9 小时前
RAG最佳实践:用 ElasticSearch 打造AI搜索系统与RAG 应用全流程详解!
人工智能·elasticsearch·大模型·大语言模型·rag·ai工具·大模型应用
醉颜凉9 小时前
Elasticsearch高阶聚合实战:Pipeline Aggregation 用法详解与典型场景全攻略
大数据·elasticsearch·jenkins
Elastic 中国社区官方博客18 小时前
Elastic-caveman : 在不损失 Elastic 最佳效果的情况下,将 AI 响应 tokens 减少64%
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·全文检索
身如柳絮随风扬21 小时前
深度解析 Elasticsearch 搜索服务:核心原理、架构与优化实践
大数据·elasticsearch·架构
kft131421 小时前
AI 驱动测试 2.0:当测试智能体成为你的“超级 QA“
大数据·人工智能·elasticsearch