IK 分词器
IK 分词器-介绍
现有问题:ES 默认对中文分词并不友好,实际上是把中文进行了每个字的分词。
# 查看ES对中文的默认分词
GET /_analyze
{
"analyzer": "standard",
"text": "乒乓球明年总冠军"
}
# 分词结果,是将“乒乓球明年总冠军”拆分成了“乒”、“乓”、“球”、“明”、“年”、“总”、“冠”、“军”
对此,通常我们需要为 ES 加入友好的中文分词器,如 IKAnalyzer 。
-
IKAnalyzer 是一个开源的、基于 Java 语言开发的、轻量级的中文分词工具包。
-
是一个基于 Maven 构建的项目。
-
具有 60 万字/秒的高速处理能力。
-
支持用户词典扩展定义。
-
下载地址:https://github.com/medcl/elasticsearch-analysis-ik/archive/v7.4.0.zip
IK 分词器-安装
环境准备:Maven
ElasticSearch 要使用 IK,就要先构建 IK 的 jar 包,这里要用到 Maven 包管理工具,而 Maven 需要 Java 环境,而 ElasticSearch 内置了 JDK, 所以可以将 JAVA_HOME 设置为ElasticSearch 内置的 JDK 。
1)设置 JAVA_HOME
vi /etc/profile
# 在profile文件末尾添加
#java environment
export JAVA_HOME=/opt/elasticsearch-7.4.0/jdk
export PATH=$PATH:${JAVA_HOME}/bin
# 保存退出后,重新加载profile
source /etc/profile
2)下载 Maven 安装包
wget https://mirrors.aliyun.com/apache/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
3)解压 Maven 安装包
tar xzf apache-maven-3.1.1-bin.tar.gz
4)设置软连接
ln -s apache-maven-3.1.1 maven
5)设置 path
- 打开文件:
vi /etc/profile.d/maven.sh
- 将下面的内容复制到文件,保存:
export MAVEN_HOME=/opt/maven
export PATH=${MAVEN_HOME}/bin:${PATH}
- 设置好 Maven 的路径之后,需要运行下面的命令使其生效:
source /etc/profile.d/maven.sh
6)验证 Maven 是否安装成功
mvn -v
7)将 Maven 镜像下载换成阿里云
vi /opt/apache-maven-3.1.1/conf/setting.xml
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
安装 IK 分词器
1)下载 IK
wget https://github.com/medcl/elasticsearch-analysis-ik/archive/v7.4.0.zip
2)解压 IK
# 如果本机环境没有安装 unzip
yum install zip
yum install unzip
# 解压 IK
unzip v7.4.0.zip
3)编译 jar 包
# 切换到 elasticsearch-analysis-ik-7.4.0目录
cd elasticsearch-analysis-ik-7.4.0/
#打包
mvn package
4) jar 包移动
- package 执行完毕后会在当前目录下生成 target/releases 目录,将其中的 elasticsearch-analysis-ik-7.4.0.zip 拷贝到 ElasticSearch 目录下的新建的目录 plugins/analysis-ik,并解压:
#切换目录
cd /opt/elasticsearch-7.4.0/plugins/
#新建目录
mkdir analysis-ik
cd analysis-ik
#执行拷贝
cp -R /opt/elasticsearch-analysis-ik-7.4.0/target/releases/elasticsearch-analysis-ik-7.4.0.zip /opt/elasticsearch-7.4.0/plugins/analysis-ik
#执行解压
unzip /opt/elasticsearch-7.4.0/plugins/analysis-ik/elasticsearch-analysis-ik-7.4.0.zip
5)拷贝辞典
- 将 elasticsearch-analysis-ik-7.4.0目录下的 config 目录中的所有文件拷贝到 elasticsearch 的 config 目录:
cp -R /opt/elasticsearch-analysis-ik-7.4.0/config/* /opt/elasticsearch-7.4.0/config
6)重启 ElasticSearch
IK 分词器-使用
分词效果
IK 分词器有两种分词模式:ik_max_word 和 ik_smart 模式
# ik_max_word:会将文本做最细粒度的拆分。
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "乒乓球明年总冠军"
}
# 分词结果:“乒乓球”、“乒乓”、“球”、“明年”、“总冠军”、“冠军”
# ik_smart:会做最粗粒度的拆分
GET /_analyze
{
"analyzer": "ik_smart",
"text": "乒乓球明年总冠军"
}
# 分词结果:“乒乓球”、“明年”、“总冠军”
由结果看出,IK 的分词效果达到我们对中文分词的要求。
查询文档
-
词条查询(term):词条查询不会分析查询条件,只有当词条和查询字符串完全匹配时才匹配搜索。
-
全文查询(match):全文查询会分析查询条件,先将查询条件进行分词,然后查询,求并集。
案例:
# 创建索引,添加映射,并指定分词器为IK分词器
PUT person2
{
"mappings": {
"properties": {
"name": { # 没指定则使用默认分词器"standard"
"type": "keyword"
},
"address": {
"type": "text",
"analyzer": "ik_max_word" # 指定分词器
}
}
}
}
# 添加文档
POST /person2/_doc/1
{
"name":"张三",
"age":18,
"address":"北京海淀区"
}
POST /person2/_doc/2
{
"name":"李四",
"age":18,
"address":"北京朝阳区"
}
POST /person2/_doc/3
{
"name":"王五",
"age":18,
"address":"北京昌平区"
}
# 查询映射
GET person2
查询分词结果:
GET _analyze
{
"analyzer": "ik_max_word",
"text": "北京昌平"
}
- 查询结果:
{
"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
}
]
}
词条查询(term)
词条查询不会分析查询条件,只有当词条和查询字符串完全匹配时才匹配搜索。
- 示例:查询“北京”
GET /person2/_search
{
"query": {
"term": {
"address": {
"value": "北京"
}
}
}
}
- 查询结果:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.13786995,
"hits" : [
{
"_index" : "person2",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.13786995,
"_source" : {
"name" : "李四",
"age" : 18,
"address" : "北京朝阳区"
}
},
{
"_index" : "person2",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.13786995,
"_source" : {
"name" : "王五",
"age" : 18,
"address" : "北京昌平区"
}
},
{
"_index" : "person2",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.12562492,
"_source" : {
"name" : "张三",
"age" : 18,
"address" : "北京海淀区"
}
}
]
}
}
- 示例:查询“北京昌平”
GET /person2/_search
{
"query": {
"term": {
"address": {
"value": "北京"
}
}
}
}
- 查询结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
全文查询(match)
# 全文查询会分析查询条件,先将查询条件进行分词,然后查询,求并集
GET /person2/_search
{
"query": {
"match": {
"address":"北京昌平"
}
}
}
查询结果:
{
"took" : 83,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.1505673,
"hits" : [
{
"_index" : "person2",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.1505673,
"_source" : {
"name" : "王五",
"age" : 18,
"address" : "北京昌平区"
}
},
{
"_index" : "person2",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.13786995,
"_source" : {
"name" : "李四",
"age" : 18,
"address" : "北京朝阳区"
}
},
{
"_index" : "person2",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.12562492,
"_source" : {
"name" : "张三",
"age" : 18,
"address" : "北京海淀区"
}
}
]
}
}