连载中 9/20

进阶查询:高亮、纠错与多字段搜索

2026-08-14 · 2224 阅读 · 0 评论 · 0 赞

排序能看了,体验还差三口气

爆款排序理顺之后,运营对搜索页的挑剔升级了:结果里关键词不高亮,用户得自己找哪里相关;把「拿铁」打成「拿贴」,零结果直接劝退;只搜商品名,藏在详情里的关键词永远搜不到。这三口气分别对应三个查询特性:highlight、suggest、multi_match。

highlight:高亮的本质是再切一遍

高亮不是把原文里的关键词做个字符串替换,而是拿查询词条对原文重新执行一次分词,命中的词条包上标记标签再还给你:

GET /product/_search
{
  "query": { "match": { "name": "燕麦拿铁" } },
  "highlight": {
    "pre_tags": [ "<em class="hl">" ],
    "post_tags": [ "</em>" ],
    "fields": {
      "name": { "number_of_fragments": 0 },
      "description": { "fragment_size": 100, "number_of_fragments": 3 }
    }
  }
}

两个字段的配置意图不同:商品名短,number_of_fragments 设 0 返回整句高亮;详情长,按 fragment_size 切出三个最相关的片段返回,避免把两千字详情整个塞给前端。默认标记是 em 标签,用 pre_tags 和 post_tags 换成自己的,前端好识别也防样式串味。两个提醒:高亮字段必须建了倒排(text),keyword 字段没有分词概念高亮意义不大;高亮不参与排序,是纯展示层动作,别指望它影响 _score。

multi_match:一搜多字段,还带加权

只搜 name 太浪费。multi_match 一个查询打多个字段,还支持按字段重要性加权:

{
  "multi_match": {
    "query": "燕麦拿铁",
    "fields": [ "name^3", "tags^2", "description" ],
    "type": "best_fields"
  }
}

name^3 表示标题命中的分数乘三——用户在标题里看到关键词,相关性天然高于在详情页末尾看到。type 有讲究:best_fields 是默认,取得分最高的那个字段;cross_fields 把多个字段当成一个大字段合并算分,适合「品牌在 A 字段、品名在 B 字段」的拆开结构;phrase 要求短语命中。老王最后用 best_fields 加标题权重,运营反馈「搜详情里提到的型号也能出来了」。

suggest:did you mean 的正确打开方式

用户打错字不该是终点。suggest 家族按场景分三种:

类型干什么适用场景
term suggester按编辑距离替换单个词条「拿贴」变「拿铁」
phrase suggester整句纠错,考虑词与词搭配整句打错的搜索框输入
completion suggester前缀自动补全搜索框边打边出联想词

completion suggester 是为补全专门设计的数据结构(基于 FST,第 2 篇见过它的名字),字段类型要配 completion,性能极快,但只认前缀、不做分词。产品化落地有个成熟套路:正常搜索有结果就正常返回;结果为空或过少,才发起一次纠错查询,把 did you mean 挂在结果页顶部,点击纠错词重新搜——而不是每次都纠错,那会显得搜索「自作聪明」。老王把这条路接上之后,「拿贴」的零结果页面第一次变成了「您是不是想找:拿铁」,客诉当场少了一半。

小结

体验三件套一句话:highlight 是展示层再分词,multi_match 是一查多字段加权,suggest 是从纠错到补全的兜底。三件事都不难,难在接入产品的姿势:高亮别动排序,纠错别每次都上,补全别拿普通查询硬扛。

搜索页齐活了,老王接着撞上经典性能墙:运营要翻到第 100 页看数据,from 加 size 翻深了直接报错。下一篇讲深分页:from 加 size 为什么越翻越贵,search_after 与 scroll 的救场姿势。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#Elasticsearch#高亮#multi_match#suggest#纠错

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞