目标 对于商品标题中的核心词进行配置相关同义词来人工提高商品搜索的准确度
现状
目前我们使用elasticsearch作为我们的数据仓库,主要存储一些商品数据。对于elasticsearch本身没有做特定的优化和定制,使用的都是默认配置,包括使用默认的standard作为分词器。索引本身没有定制。
目前的查询
1 | GET /shop/item/_search?pretty |
请忽略这里多余的bool和must,因为在实际的查询业务中,我们还会有其他判断条件来帮助筛选精度,目前测试数据是在上述筛选条件已经执行后剔除出来的干净数据。
结果集为
1 | { |
这里的结果与我们实际的业务输出结果也类似,我们业务搜索的时候限制了条数为10条,但是真正的目标数据缺因为匹配score的原因,隐藏在了后面。
1 | GET /shop/item/30?pretty |
问题分析
- 首先默认分词对于中文来说是按照逐字分词,这样就丢失了词语本身的意义,在es的默认使用的tf-idf算法中会引入一些长尾问题;
- 其次洗面奶->洁面膏, ml->毫升这种同义词词组应该被识别出来。
解决
引入ik分词
IKAnalyzer是一个开源的,基于Java语言开发的轻量级的中文分词语言包,它是以Lucene为应用主体,结合词典分词和文法分析算法的中文词组组件。从3.0版本开始,IK发展为面向java的公用分词组件,独立Lucene项目,同时提供了对Lucene的默认优化实现。
安装ik分词
- 可以选择下载预编译包
解压插件包到your-es-root/plugins
, 建议重命名文件夹名为analysis-ik。效果如下1
2
3
4└─plugins
└─analysis-ik
└─config
└─custom
注意 下载的插件版本最好和当前使用的es版本一致。
- 可以选择使用
elasticsearch-plugin
来安装(仅支持v5.5.1以上版本)1
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.6.2/elasticsearch-analysis-ik-5.6.2.zip
重启elasticsearch
验证安装
- 启动时的日志
重启后会看到loaded plugin [analysis-ik]
日志 - 调用分词进行验证 相对应可以试试对比默认分词的效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26GET _analyze?analyzer=ik_smart&pretty=true&text="中华人民共和国国旗 150ml"
{
"tokens": [
{
"end_offset": 7,
"position": 0,
"start_offset": 0,
"token": "中华人民共和国",
"type": "CN_WORD"
},
{
"end_offset": 9,
"position": 1,
"start_offset": 7,
"token": "国旗",
"type": "CN_WORD"
},
{
"end_offset": 15,
"position": 2,
"start_offset": 10,
"token": "150ml",
"type": "LETTER"
}
]
}ik分词有细粒度1
GET _analyze?analyzer=standard&pretty=true&text="中华人民共和国国旗 150ml"
ik_max_word
与智能分词ik_smart
两种切分模式,根据实际情况,我们默认采用智能分词。
重建索引
1 | DELETE /shop |
验证分词
1 | GET /shop/item/_search?pretty |
可以看到结果已经按照中文词组进行分词了,同时也可以看到150ml没有产生任何映射作用
配置ik同义词
在elastic-root-path/config/analysis
中新建synonyms.txt
配置文件。
在synonyms.txt
中加入以下配置
1 | 洁面膏,洗面奶 |
重新配置索引
1 | PUT /shop |
重新验证
1 | GET /shop/item/_search?pretty |
结果
1 | { |
从结果可以看出,id为30的条目已经被成功搜索出来了。目的达到,接下来要做的就是维护自定义词典与同义词库,优化搜索效果。