Elasticsearch搜索排名优化
虽然使⽤ ES 可以非常⽅便快速地搭建出搜索平台,但搜出来的结果往往不符合预期。
一、使⽤ bool 查询的 filter 增加筛选
1、问题:
我们应该避免直接让⽤户针对所有内容进⾏查询,这样会返回⼤量的命中结果
2、分析:
针对这种情况,我们可以给内容增加⼀些标签、分类等筛选项提供给⽤户做选择,以达到更好的结果排名。这 样搜索时被 ES 引擎评分的⽬标结果将会变少,评分的抖动影响会更⼩。
实现这个功能就使⽤到 bool 查询的过滤器。bool 查询中提供了4个语句:
must / filter / should / must_not
其 中 filter / must_not 属于过滤器,must / should 属于查询器。
关于过滤器,你需要知道以下两点:
- 过滤器并不计算相关性评分,因为被过滤掉的内容不会影响返回内容的排序;
- 过滤器可以使⽤ ES 内部的缓存,所以过滤器可以提⾼查询速度。
上⾯的⽰例中,存在⼀个⼩技巧,即使⽤标签的 id 来进⾏筛选。因为 tags 字段是text 类型的,term 查询是精 确匹配,不要将其应⽤到 text 类型的字段上,如果text字段要被过滤器使⽤,在 mappings 中应该要使⽤ string 类型(它将字段映射到两个类型上,text 和 keyword )或者 keyword 类型。
二、使⽤ match_phrase 提⾼搜索短语的权重
1、问题:
搜索的时候经常会出现搜索结果和搜索关键词不是连续匹配的情况。
例如搜索关键词为:“2020年 微信⽤户研究报告”,⽽返回的结果⼤多数是匹配“微信”、“⽤户”、“研究”、“报告”这些零散的关键词,⽽⽤户想要 匹配整个短语的结果却在后⾯
2、分析:
先把查询关键词经过 search_analyzer 设置的分析器分析,再把分析器得到的结果挨个放进 bool 查询 中的 should 语句,这些 should 没有权重与顺序的差别,并且只要命中⼀个should 语句的文档都会被返回。转 换语句如下图所⽰,前⾯是原语句,后⾯是转换后的语句
三、should 语句结合使⽤ match 与 match_phrase
1、问题:
在DSL中是使⽤ match_phrase 查询。 match_phrase 要求必须命中所有分词,并且返回的文档命中的词也要按照查询短语的顺序,词的间距可以使⽤ slop 设置。
2、分析:
match_phrase 虽然帮我们解决了顺序的问题,但是它要求比较苛刻,需要命中所有分词。如果单独使⽤它来进 ⾏搜索,会发现搜索出来的结果相比 match 会⼤⼤减少,这是因为匹配若⼲个词的文档和匹配顺序不对的文档 都没被返回。
这时候可以采⽤ bool 查询的 should 语句,同时使⽤ match 与 match_phrase 查询语句,这样相当于 match_pharse 提⾼了搜索短语顺序的权重,使得能够顺序匹配到的文档相关性评分更⾼。
四、使⽤ boost 调整查询语句的权重
1、问题:
有⼀个显⽽易⻅的问题:所有字段都⽆权重之分。根据常识我们知道,title 的权重应该 ⾼于其他字段,显然不能和其他字段是⼀样的得分。
2、分析:
查询时可以⽤ boost 配置来增加权重,不过这⾥设置的对象并不是某个字段,⽽是查询语句。设置后,查询语 句的得分等于默认得分乘以 boost。
设置 boost 有⼏个需要注意的地⽅:
- 数据质量⾼的字段可以相应提⾼权重;
- match_phrase 语句的权重应该⾼于相应字段 match 查询的权重,因为文档中按顺序匹配的短语可能数量 不会太多,但是查询关键词被分词后的词语将会很多,match的得分将会比较⾼,则 match 的得分将会 冲淡 match_phrase 的影响;
- 在 mappings 设置中,可以针对字段设置权重,查询时不⽤再针对字段使⽤ boost 设置。