深入学习 ElasticSearch 的搜索(六):搜索语法总结
深入学习 ElasticSearch 的搜索六搜索语法总结前面几篇分别整理了Query DSLmatchmatch_phrasetermbool这一篇做一次总结把这些查询放到同一张图里理解。ElasticSearch 搜索最容易混淆的点通常不是语法本身而是没有分清字段是text还是keyword查询是否会走 analyzer条件是用于评分还是用于过滤查询目标是全文检索还是精确匹配一、先按字段类型判断ElasticSearch 搜索之前先看字段类型。Mapping 可以理解为索引的字段结构说明书。它决定字段应该如何被索引、如何被搜索。也就是说搜索设计的第一步不是写 DSL而是先判断字段身份自然语言内容通常用text结构化精确值通常用keyword、数字、日期、布尔等类型字段身份错了后面的查询再复杂也很难自然。1. text 字段text字段会分词。适合标题正文摘要评论描述信息常用查询matchmatch_phrase例如POSTarticle_search/_search{query:{match:{content:ElasticSearch 倒排索引}}}2. keyword 字段keyword字段通常不分词。适合分类状态标签用户 ID订单号枚举值常用查询termtermsbool.filter例如POSTarticle_search/_search{query:{term:{category:elasticsearch}}}3. multi-fields实际项目中同一个字段经常既需要全文检索又需要精确匹配。这时可以使用 multi-fieldsPUTarticle_search_v2{mappings:{properties:{nickname:{type:text,fields:{keyword:{type:keyword}}}}}}这样nickname用于match、match_phrasenickname.keyword用于term、排序、聚合这也是很多搜索系统里最常见的字段建模方式。二、match、match_phrase、term 的区别可以用下面这张表理解。查询是否分析查询文本适合字段典型用途match是text全文关键词搜索match_phrase是text连续短语搜索term否keyword精确值匹配一句话记忆match 查词match_phrase 查短语term 查精确值。三、match 怎么用match是全文检索入口。POSTarticle_search/_search{query:{match:{content:ElasticSearch 搜索}}}适合用户输入关键词搜文章正文搜标题搜自然语言文本关键点查询文本会被 analyzer 分析命中结果会计算_score默认比较宽松可以用operator或minimum_should_match控制严格程度四、match_phrase 怎么用match_phrase用于短语查询。POSTarticle_search/_search{query:{match_phrase:{content:倒排索引}}}适合搜固定表达搜连续标题搜日志片段提高结果精确度关键点查询文本也会被 analyzer 分析不只看 term 是否出现还看 position可以用slop放宽距离五、term 怎么用term用于精确词项查询。POSTarticle_search/_search{query:{term:{status:published}}}适合查状态查分类查用户 ID查枚举值查精确标签关键点不要用它做普通全文搜索对text字段使用时要特别小心最常搭配keyword字段六、bool 怎么用bool用来组合多个条件。POSTarticle_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必须不匹配七、一套常用业务搜索模板很多后台搜索都可以从这个模板开始POSTarticle_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做排序八、高亮和返回字段控制业务搜索通常还需要控制返回字段和高亮。例如只返回标题、分类、创建时间并对正文命中的关键词做高亮POSTarticle_search/_search{_source:[title,category,created_at],query:{match:{content:ElasticSearch}},highlight:{fields:{content:{}}}}其中_source控制返回哪些原始字段highlight控制命中片段高亮如果文档很大合理控制_source可以减少网络传输和客户端处理成本。九、分页要注意什么普通分页可以使用from和size。POSTarticle_search/_search{from:20,size:10,query:{match_all:{}}}它适合浅分页。如果页数很深例如翻到几千页from size的成本会明显升高。深分页场景通常要考虑search_afterPIT避免无限制跳页普通后台列表可以先用from size但要限制最大翻页深度。十、前缀、通配和联想搜索搜索框输入时通常有两种模式搜索结果页用户输入完整关键词后搜索联想建议用户边输入边出结果正式搜索结果页更重视排序质量通常使用multi_match bool phrase boost联想建议更重视响应速度和前缀匹配可以考虑match_bool_prefixsearch_as_you_typecompletion suggesteredge_ngram通配符查询如wildcard虽然直观但不要轻易当主查询。POSTarticle_search/_search{query:{wildcard:{author:*adm*}}}这类查询在大数据量下可能比较重而且排序语义也不如全文查询自然。真要大量使用通配搜索最好从 mapping 层专门设计。十一、小说分块搜索的字段建模例子如果是小说分块或内容 chunk 搜索字段可以按用途拆开。示例文档{book_id:book_001,chapter_index:12,chapter_title:武当山上,chunk_text:饭后张三丰看着郭靖没有说话。,entity_names:[张三丰,郭靖],start_line:120,word_count:86}建议的搜索语义chunk_text正文全文搜索用match/match_phrasechunk_text.keyword整段完全相等时才用termentity_names人名实体精确检索用term/termsbook_id书籍过滤用termchapter_index、start_line、word_count范围过滤用range一个完整查询可以这样写POSTarticle_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先确认字段类型。GETarticle_search/_mapping重点看字段是不是text字段是不是keyword字段用了哪个 analyzer是否配置了search_analyzer2. 看 analyzer用_analyze看文本会被拆成什么。POSTarticle_search/_analyze{field:content,text:ElasticSearch 倒排索引}如果分词不符合预期先解决 analyzer。3. 看查询类型确认是不是用错了查询全文搜索却用了term精确过滤却用了match短语搜索却用了普通match多条件查询没有用bool4. 看 filter 和 score如果某些过滤条件影响了排序检查是否把本该放filter的条件放进了must。如果结果太多考虑operator: andminimum_should_matchmatch_phrase增加filter十三、排查评分explain 和 profile如果想知道某篇文档为什么命中、为什么评分高可以用_explain。GETarticle_search/_explain/1{query:{match:{content:ElasticSearch}}}如果想分析查询执行过程和耗时可以在搜索请求中开启profile。POSTarticle_search/_search{profile:true,query:{match:{content:ElasticSearch}}}这两个工具适合排查问题不建议在普通业务请求中长期打开。十四、为什么排序有时看起来不合理ElasticSearch 默认会根据相关性模型计算_score常见默认模型是 BM25。搜索结果看起来“不合理”通常不是单个 DSL 语法错了而是这些因素叠加字段类型设计错了应该精确查的字段走了全文搜索字段权重没有配置短语优先没有做过滤条件写进了must污染了评分fuzzy、wildcard被当成主查询常见优化方式给重要字段更高 boost用.keyword做精确命中加权用match_phrase给完整短语加分结构化条件放入filter十五、最常用的判断口诀可以按下面方式选择查询搜正文标题match 搜连续短语match_phrase 搜分类状态term 多个条件组合bool 结构化过滤bool.filter 排除数据bool.must_not 提升相关性bool.should再结合字段类型text - match / match_phrase keyword - term / terms number/date - range / term十六、一句话总结ElasticSearch 搜索语法的核心不是背 API而是先分清查询意图。最终可以这样理解用户输入的自然语言用 match需要连续短语用 match_phrase结构化精确值用 term多个条件组合用 bool。只要把字段类型、分词结果、查询类型这三件事对齐大部分搜索问题都会变得容易排查。参考链接Query DSLhttps://www.elastic.co/docs/query-languages/query-dslMatch queryhttps://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-queryTerm queryhttps://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-term-queryBoolean queryhttps://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-queryHighlightinghttps://www.elastic.co/docs/reference/elasticsearch/rest-apis/highlightingPaginate search resultshttps://www.elastic.co/docs/reference/elasticsearch/rest-apis/paginate-search-results