ElasticSearch 中Ik分词搜索遇到的一个问题
场景描述
电商应用商品搜索功能
elasticSearch 版本:7.1.17
商品数据存放在名为 goods 的 index 中
用于搜索的字段 goods_name 类型为 text,配置了 ik 分词器,模式为 ik_smart
{
"mappings": {
"goods_name": {
"type": "text",
"analyzer": "ik_smart"
}
}
}
ik 字典配置内容如下:
科颜氏
科颜氏高保湿
现在 goods 中有以下两行文档
goods_id | goods_name |
---|---|
1 | 科颜氏面霜 |
2 | 科颜氏高保湿精粹爽肤水 |
程序使用关键字科颜氏
进行搜索,es 命中了 goods_id 为1,goods_name 为 科颜氏面霜的文档
此时,期望同时命中goods_name 为 科颜氏面霜
和 科颜氏高保湿精粹爽肤水
的文档,但是实际上只命中了一行。
程序使用关键字科颜氏高保湿
进行搜索,es 命中了 goods_id 为2,goods_name 为 科颜氏高保湿精粹爽肤水的文档
问题分析
由于 goods_name 配置的分词模式为 ik_smart
,在 ik 字典配置了 科颜氏
和 科颜氏高保湿
这两个词条的情况下,科颜氏高保湿精粹爽肤水 的 es 分词结果如下:
可见,由于字典单独配置了科颜氏高保湿,在ik_smart模式下分词结果中并未出现科颜氏
,只有更为准确的科颜氏高保湿
,这就导致通过 科颜氏
进行查询时无法命中此文档。
解决方案
首先,明确需求,我的需求是在通过一个范围更大的关键词进行查询时需要命中尽可能多的文档,通过范围更小的关键字查询时,命中更准确的文档。那么,如何解决这个问题呢。
已知 ik 有两种分词策略:ik_smart
及 ik_max_word
,看下两次策略的分词效果
ik_smart
最少切分
ik_max_word
最大粒度切分
可见,在使用 ik_smart
策略时,分词的结果是尽可能小的,而使用 ik_max_word
时,我们可以获得最大粒度也就是尽可能多的拆词结果。
回到我们的需求,我们需要让搜索词命中更多的结果,那么我们需要做两件事情:
- 搜索词做最小粒度拆分,即使用
ik_smart
策略,保证科颜氏
的分词结果是 科颜氏 - 索引中的数据做最大粒度拆分,即使用
ik_max_word
策略,让科颜氏高保湿精粹爽肤水
的分词结果即包含科颜氏,又包含科颜氏高保湿,让此文档尽可能的被命中
后续改进
由于索引中的数据在使用 `ik_max_word
` 策略进行分词后会被做最大粒度的拆分,这也导致当某些搜索词未在字典中进行配置的时候,可能会出现一些低相关的结果,如名称中只是出现了一个一个搜索词中的单字,也被搜索出来了。
为了解决这个问题,可以考虑尽可能的配置完善的字典,也可以考虑排除低得分的文档,这个部分后续进行进一步的学习研究。
转载自:https://juejin.cn/post/7229258224910204989