1.索引结构 2.分词的结果 3.分词配置 4.匹配规则 5.处理方案 ## 索引的商品名称字段结构 ```agsl "prodName" : { "type" : "text", "analyzer" : "ik_max_word", "search_analyzer" : "ik_smart" } ``` ### 分析器: analyzer: 插入文档时,将text类型的字段做分词然后插入倒排索引 search_analyzer: 在查询时,先对要查询的text类型的输入做分词,再去倒排索引搜索 ### 分词模式: ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。 ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。 插入文档(analyzer)时用ik_max_word,在查询(search_analyzer)时用ik_smart 即:索引时最大化的将文章内容分词,搜索时更精确的搜索到想要的结果。 ## 自定义词库 分词的时候针对一些特殊的词语在分词的时候也需要能够识别,公司产品的名称或者网络上新流行的词语 假设我们公司开发了一款新产品,命名为:数据大脑,我们希望ES在分词的时候能够把这个产品名称直接识别成一个词语。 现在使用ik分词器测试一下分词效果: ```agsl GET _analyze { "analyzer":"ik_smart", "text":"数据大脑" } ``` 分词结果 ```agsl { "tokens" : [ { "token" : "数据", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 0 }, { "token" : "大脑", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 1 } ] } ``` 根据上面的分词结果,查询时输入数据大脑,会先分词为`数据`和`大脑`,然后再去文档中进行分词匹配 如果我们不用完整的词语,换成单个字,或者分词中没有分到的词语来进行查询,比如`数`、 `大` 和 `据大`, 就会匹配不到商品了 这也是es分词查询和mysql模糊查询的不同 想要es中输入`数`、 `大` 和 `据大`时也要匹配到名称为`数据大脑`的商品,就要用到自定义词库了 在自定义词库文件中配置上`数`、 `大` 和 `据大`,然后再重启es重新测试一下分词效果: ```agsl GET _analyze { "analyzer":"ik_smart", "text":"数据大脑" } ``` 分词结果 ```agsl { "tokens" : [ { "token" : "数据", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 0 }, { "token" : "数", "start_offset" : 0, "end_offset" : 1, "type" : "CN_WORD", "position" : 1 }, { "token" : "据大", "start_offset" : 1, "end_offset" : 3, "type" : "CN_WORD", "position" : 2 }, { "token" : "据", "start_offset" : 1, "end_offset" : 2, "type" : "CN_WORD", "position" : 3 }, { "token" : "大脑", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 4 } ] } ``` 从分词结果中可以看到,自定义词库文件中配置的`数`、 `大` 和 `据大`都进行了分词,`大`和`脑`没有配置到自定义分词文件中,分词后还是已词组的方式存在 因此为了扩大查询范围,部署模板中的es有设置自定义词库,词库中包含了每个汉字又会出现其他问题,一个是分词结果会很多,另一个是分词太多会导致排序不准确(看下面的排序) 所以建议平台要维护自己分词词库,模板中配置的自定义词库更多是为了扩大搜索范围,无法保证排序是否精确 ## 搜索排序 搜索的相关性以及算分机制 什么是相关性算分? - 相关性算分描述了一个文档和查询语句的匹配程度,ES 会对查询到的每个文档进行打分,打分的本质就是排序 - ES5 之前默认的相关性打分采用 TF-IDF 算法,TF-IDF 是信息检索领域最重要的发明,现代搜索引擎都对 TF-IDF 做了大量细微的优化 - ES6 之后开始采用 BM25 算法(对 TF-IDF 的改进),当 TF 无限增加时, BM 25 算法会使之趋于一个稳定的数值 - 在 ES 中查询加上 explain=true 可以查看当前查询是如何打分的 - 影响相关性算分的几个因子: 1. 词频-TF(Term Frequency):检索词在一篇文档中出现的频率,频率越高,权重越大 2. 文档频率-DF(Document Frequency)- 检索词出现的文档数量占总文档数量的比重,DF 越大,出现的文档数越多,说明对应用意义越小,该词的相关性也就越小, 比如 "and", "is" 这些词出现非常频繁,用户反而不关心 3. 逆向文档频率-IDF(Inverse document frequency)- 因为 DF 的值算出来结果范围会非常大,为了减少 DF 对打分的影响,引入了 IDF,其实就是对 DF 取对数来减少打分影响 5. 字段长度(Field-length)- 搜索的字段越短,相关性越高