前面的范例创建索引、搜索数据时都是使用默认的分词器,因为存储的都是中文,所以分词效果不太理想,会把text
的字段分成一个个汉字,为了更好地对中文内容进行分词,需要更加智能的IK分词器。
首先在GitHub官网搜索elasticsearch-analysis-ik
并下载,也可以直接前往下载地址下载。
下面介绍Docker
环境下下安装IK分词器,Docker
安装Elasticsearch
请参考Docker安装Elasticsearch + Kibana一文,这里不做累述。
$ cd /data/docker/elasticsearch/plugins
$ mkdir ik
$ cd ik
$ wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.13.2/elasticsearch-analysis-ik-7.13.2.zip
$ unzip elasticsearch-analysis-ik-7.13.2.zip
$ docker restart es01
# 查看启动日志,检查加载IK分词器是否成功
$ docker logs es01 | grep analysis-ik
若出现loaded plugin [analysis-ik]
日志信息,则表示IK分词器加载成功。
以下时未使用IK分词器的范例:
POST _analyze
{
"text": "时光流逝,我对你的爱却与日俱增"
}
分词后的结果如下:
以上范例使用默认的分词器,会把中文内容分词成单独的汉字。下面来看使用IK分词器的范例:
POST _analyze
{
"analyzer": "ik_max_word",
"text": "时光流逝,我对你的爱却与日俱增"
}
分词后的结果如下:
利用IK分词器,以上内容被分词为:
["时光流逝", "时光", "流逝", "我", "对", "你", "的", "爱", "却与", "与日俱增", "与日", "俱", "增"]
值得注意的是:
IK分词器有以下两种分词模型:
ik_max_word
模式ik_smart
模式一般在创建索引时会明确指定分词的模式,总共有两种操作:一种是让所有text
类型的字段都使用分词模式,另一种是给每一种text
类型的字段指定分词模式。
下面的范例是所有text
类型的字段都是用同一种分词模式:
# 创建索引模板,所有“text”类型的字段都使用IK分词器的“ik_max_word”模式
PUT myindex
{
"settings": {
"analysis": {
"ik": {
"tokenizer": "ik_max_word"
}
}
},
"mappings": {
"properties": {
"field1": {
"type": "text"
}
}
}
}
下面的范例为每一个text
类型字段分别指定特定的分词模式:
PUT myindex
{
"mappings": {
"properties": {
"field1": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"field2": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "standard"
},
"field3": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
}
}
}
由以上语句可知,field1
字段使用ik_max_word
分词模式,field2
字段使用默认的standard
分词模式,field3
字段使用IK分词器的ik_smart
模式。
下面的范例存储和搜索使用不同的分词模式:
# 创建索引映射,存储时使用IK分词器的ik_max_word模式,搜索时使用IK分词器的ik_smart模式
PUT myindex
{
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"address": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"age": {
"type": "integer"
}
}
}
}
# 插入文档数据
POST myindex/_doc
{
"name": "曹操",
"address": "魏国",
"age": 18
}
# 插入文档数据
POST myindex/_doc
{
"name": "张辽",
"address": "魏国",
"age": 19
}
# 插入文档数据
POST myindex/_doc
{
"name": "刘备",
"address": "蜀国",
"age": 30
}
# 插入文档数据
POST myindex/_doc
{
"name": "姜维",
"address": ["魏国", "蜀国"],
"age": 20
}
POST myindex/_doc
{
"name": "孙十万",
"address": "吴国",
"age": 35
}
# 全文搜索address等于“魏国”的数据
GET myindex/_search
{
"query": {
"match": {
"address": "魏国"
}
}
}
返回结果如下:
可以看到,返回的结果都符合我们的预期。
下面的语句将使用最细粒度的搜索:
GET myindex/_search
{
"query": {
"match": {
"address": {
"query": "魏国",
"analyzer": "ik_smart"
}
}
}
}
需要注意的是,因为我们在设置映射模板的时使用最细粒度进行分词存储(分词尽可能多),所以在搜索时可以指定对最细粒度的分词模式和最粗粒度的分词模式分别搜索。在正式项目的使用中也推荐这种做法,存储时选择尽量细的分词规则,这样在搜索时可以指定符合具体项目要求的分词模式。