es搜索优化实战

1、功能需求

根据微信备注、昵称、微信号、来搜索好友、单聊

根据群聊名称搜索群聊

能根据汉语拼音,汉语拼音前缀来进行搜索

2、优化前:走的ES模糊搜索,性能差,请求慢

3、优化后:使用分词器,利用ES倒排索引特性,加快查询速度

4、优化方案如下:使用standard分词器,结合ES的minimum_should_match特性

理由一:传统的中文分词器IK,拼音分词器,并不能很好适合天权“微信搜索”的需求场景、比如,姓名,昵称,微信号、备注,往往并不是生活中的常用词汇,且文本短。

理由二:可根据线上使用情况,动态的调整搜索结果的相关度(设置minimum_should_match百分比)

理由三:standard是一个英文分词器,对于所有的中文字符,会对每个中文字符进行分词的特点。此特性,结合minimum_should_match拥有良好的实战效果。虽然ik_max_word拥有对中文语句的分词细致化的良好效果,但是远远不如standard,对每个中文字符进行分词来的细致

/**

  • 用 standard 分词器 细分 中文词语,解决分词不够细致的问题
    */
    @ESMapping(datatype = DataType.text_type, analyzer = Analyzer.standard, search_analyzer = Analyzer.standard)
    private String assist;

用例一:设置 minshouldmatch = 80%,搜索关键字 key = “刘德华的”,存储ES doc文档 assist = “刘德华 川 105期数学 horken_kason liudehua liude liu ldh ld l”。

              搜索底层步骤:

                     第一步:对key进行分词,使用standard分词器。分词后的词汇为:“刘” “德” “华” “的” , 4个词

                     第二步:4 个term查找 { "term": { "body": "刘"}} ... 结果 3 个命中,“刘” “德” “华” 命中,“的”字没有命中

' 第三步:4个term最少需要命中80%,4 * 0.8 = 3.2 向下取整为 3

                     第四步:判断必须命中数和已经命中数的大小 3 >= 3,所以这条doc作为搜索结果

用例二:设置 minshouldmatch = 80%,搜索关键字 key = “刘啦德的华”,ES的文档里 assist = “刘德华 川 105期数学 horken_kason liudehua liude liu ldh ld l”。

              搜索底层步骤:

                    第一步:对key进行分词,使用standard分词器。分词后的词汇为:“刘” “啦” “德” “的” “华” ,5个词

                    第二步:5个term 查找{ "term": { "body": "刘"}} ...,只有3个命中,“刘” “德” “华” 命中

                    第三步:5个term最少需要命中80%,5 * 0.8 = 4 向下取整为 4

                    第四步:3 < 4,这条doc不能作为搜索的结果

5、效果如下
image.png

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.fengpt.cn/archives/es搜索优化实战