前言

前面的案例使用standard、english分词器,是英文原生的分词器,对中文分词支持不太好。中文作为全球最优美、最复杂的语言,目前中文分词器较多,ik-analyzer、结巴中文分词、THULAC、NLPIR和阿里的aliws都是非常优秀的,我们以ik-analyzer作为讲解的重点,其它分词器可以举一反三。

概要

本篇主要介绍中文分词器ik-analyzer的安装使用、自定义词库以及热更新方案。

分词器插件安装

我们Elasticsearch 6.3.1版本为例,集成IK分词器,其他的分词器过程也类似,在ES的bin目录下执行插件安装命令即可:

./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.1/elasticsearch-analysis-ik-6.3.1.zip

其中install后面的那个的地址是 elasticsearch-analysis-ik 的github release对应ES版本的下载地址。

插件的版本最好与Elasticsearch版本保持一致,如果Elasticsearch为别的版本,下载对应版本的ik-analyzer插件即可。

安装成功后,ES启动日志就能看到如下信息:

[2019-11-27T12:17:15,255][INFO ][o.e.p.PluginsService] [node-1] loaded plugin [analysis-ik]

IK分词器

基础知识

IK分词器包含两种analyzer,一般用ik_max_word

ik_max_word:会将文本做最细粒度的拆分

ik_smart:会做最粗粒度的拆分

测试分词效果

# ik_max_word分词测试
GET /_analyze
{
"text": "您好祖国",
"analyzer": "ik_smart"
} # 响应如下:
{
"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
}
]
}
# ik_max_word分词测试
GET /_analyze
{
"text": "我和我的祖国",
"analyzer": "ik_max_word"
} # 响应如下:
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "和我",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
},
{
"token": "的",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 2
},
{
"token": "祖国",
"start_offset": 4,
"end_offset": 6,
"type": "CN_WORD",
"position": 3
}
]
}

配置文件

ik插件安装完成后,可以在elasticsearch-6.3.1/config/analysis-ik看到ik的配置文件IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

该目录下带有许多文件,含义如下:

  • main.dic ik 原生内置的中文词库,里面有275909条现成的词语
  • quantifier.dic 量词和单位名称,如个,斤,克,米之类的
  • suffix.dic 常见后缀词,如江,村,省,市,局等
  • surname.dic 中国姓氏
  • stopword.dic 停用词,目前默认的是写的几个英文单词,如and, a, the等
  • preposition.dic 副词、语气助词,连接词等无实际含义的词语,如却,也,是,否则之类的

6.3.1版本的IK分词器还提供了额外的词库补充文件,extra开头的那几个就是,如extra_main.dic,共收录398716条现有的词语,默认没有使用,有需要可以在配置文件IKAnalyzer.cfg.xml上添加,其他类似。

最重要的是main.dic和stopword.dic。stopword(停用词),分词时会直接被干掉,不会建立在倒排索引中。

自定义词库

  1. 创建自定义词库文件mydic.dic,并在IKAnalyzer.cfg.xml的ext_dict属性里加上该文件名,可以在mydic.dic文件里补充自己的词汇,如网络流行词:跪族篮孩。

添加前的分词效果:

GET /forum/_analyze
{
"text": "跪族篮孩",
"analyzer": "ik_max_word"
} 响应结果:
{
"tokens": [
{
"token": "跪",
"start_offset": 0,
"end_offset": 1,
"type": "CN_WORD",
"position": 0
},
{
"token": "族",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 1
},
{
"token": "篮",
"start_offset": 2,
"end_offset": 3,
"type": "CN_WORD",
"position": 2
},
{
"token": "孩",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 3
}
]
}

添加词库后:

{
"tokens": [
{
"token": "跪族篮孩",
"start_offset": 0,
"end_offset": 4,
"type": "CN_WORD",
"position": 0
},
{
"token": "跪",
"start_offset": 0,
"end_offset": 1,
"type": "CN_WORD",
"position": 1
},
{
"token": "族",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 2
},
{
"token": "篮",
"start_offset": 2,
"end_offset": 3,
"type": "CN_WORD",
"position": 3
},
{
"token": "孩",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 4
}
]
}

能看到完整的“跪族篮孩”,能看到完整的语词出现。

2)自己建立停用词库,如了,的,哈,啥,这几个字不想去建立索引

在配置文件IKAnalyzer.cfg.xml下ext_stopwords标签添加:extra_stopword.dic,并加几个词,修改后同样要重启es。

例:加一个"啥"字在ext_stopword中

修改前:

GET /forum/_analyze
{
"text": "啥都好",
"analyzer": "ik_max_word"
} 响应结果:
{
"tokens": [
{
"token": "啥",
"start_offset": 0,
"end_offset": 1,
"type": "CN_WORD",
"position": 0
},
{
"token": "都好",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
}
]
}

添加停用词后

{
"tokens": [
{
"token": "都好",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 0
}
]
}

那个啥字直接没有了,结果符合预期。

热更新方案

上面自定义词库有一个致命问题:必须要重启ES,新增的词库才能生效。

研发、测试环境自己玩玩无所谓,多半是自己使用,节点又少,重启就重启,关系不大。但想想生产环境能随便让你重启吗?动辄几百个ES实例,重启的事就别想了,另外找办法。

由此引出现在的热更新需求,让ES不停机能立即加载新增的词库。

热更新的方案

  1. 基于id分词器原生支持的更新方案,部署一个web服务器,提供一个http接口,通过modified和try两个http响应头,来提供词语的热更新操作。
  2. 修改ik分词器源码,然后手动支持从mysql中每隔一定时间,自动加载新的词库。

推荐方案二,方案一虽是官方提供的,但操作起来比较麻烦,还需要部署http服务器。

方案步骤

1)下载源码

git clone https://github.com/medcl/elasticsearch-analysis-ik

git checkout tags/v6.3.1

该工程是Maven项目工程,将代码导入IDEA或Eclipse。

2)修改点

org.wltea.analyzer.dic.Dictionary

主要思路是在这个类的initial()方法内增加一个入口,反复去调用reLoadMainDict()方法,此方法如下:

public void reLoadMainDict() {
logger.info("重新加载词典...");
// 新开一个实例加载词典,减少加载过程对当前词典使用的影响
Dictionary tmpDict = new Dictionary(configuration);
tmpDict.configuration = getSingleton().configuration;
tmpDict.loadMainDict();
tmpDict.loadStopWordDict();
_MainDict = tmpDict._MainDict;
_StopWords = tmpDict._StopWords;
logger.info("重新加载词典完毕...");
}

这个方法就是重新加载词库的,然后修改loadMainDict()和loadStopWordDict()方法,在这两个方法最后加上读取数据库获取最新的数据记录的逻辑即可。数据库的表结构自己定义两张表,满足数据库表设计规范即可。

3)IDE上mvn package打包

可以直接用target/releases/目录下的elasticsearch-analysis-ik-6.3.1.zip

4)解压zip包,加上jdbc的配置,该修改的修改,重启ES,看日志

5)在数据库里加几个字段,在线尝试是否生效。

方案延伸

该方案使用数据库轮询的方法,简单有效,但比较浪费资源,毕竟生产上修改词库的动作是按需求发生的,可以考虑由定时轮询改成MQ消息通知,这样就可以做到按需更新,而不用浪费太多的资源做词典更新。

小结

本篇对中文分词器IK作了简单的讲解,市面上流行的中文分词器很多,如果我们遇到有中文分词的需求,货比三家是永远不过时的道理,调研可能要花费一些时间,但能挑到适合自己项目的分词器,还是划算的。

专注Java高并发、分布式架构,更多技术干货分享与心得,请关注公众号:Java架构社区

可以扫左边二维码添加好友,邀请你加入Java架构社区微信群共同探讨技术

Elasticsearch系列---使用中文分词器的更多相关文章

  1. elasticsearch使用ik中文分词器

    elasticsearch使用ik中文分词器 一.背景 二.安装 ik 分词器 1.从 github 上找到和本次 es 版本匹配上的 分词器 2.使用 es 自带的插件管理 elasticsearc ...

  2. 如何在Elasticsearch中安装中文分词器(IK)和拼音分词器?

    声明:我使用的Elasticsearch的版本是5.4.0,安装分词器前请先安装maven 一:安装maven https://github.com/apache/maven 说明: 安装maven需 ...

  3. Elasticsearch:hanlp 中文分词器

    HanLP 中文分词器是一个开源的分词器,是专为Elasticsearch而设计的.它是基于HanLP,并提供了HanLP中大部分的分词方式.它的源码位于: https://github.com/Ke ...

  4. Elasticsearch:IK中文分词器

    Elasticsearch内置的分词器对中文不友好,只会一个字一个字的分,无法形成词语,比如: POST /_analyze { "text": "我爱北京天安门&quo ...

  5. 如何在Elasticsearch中安装中文分词器(IK+pinyin)

    如果直接使用Elasticsearch的朋友在处理中文内容的搜索时,肯定会遇到很尴尬的问题--中文词语被分成了一个一个的汉字,当用Kibana作图的时候,按照term来分组,结果一个汉字被分成了一组. ...

  6. elasticsearch之集成中文分词器

    IK是基于字典的一款轻量级的中文分词工具包,可以通过elasticsearch的插件机制集成: 一.集成步骤 1.在elasticsearch的安装目录下的plugin下新建ik目录: 2.在gith ...

  7. ElasticSearch安装中文分词器IKAnalyzer

    # ElasticSearch安装中文分词器IKAnalyzer  本篇主要讲解如何在ElasticSearch中安装中文分词器IKAnalyzer,拆分的每个词都是我们熟知的词语,从而建立词汇与文档 ...

  8. 搜索引擎ElasticSearch系列(五): ElasticSearch2.4.4 IK中文分词器插件安装

    一:IK分词器简介  IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本.最初,它是以开源 ...

  9. ElasticSearch搜索引擎安装配置中文分词器IK插件

    近几篇ElasticSearch系列: 1.阿里云服务器Linux系统安装配置ElasticSearch搜索引擎 2.Linux系统中ElasticSearch搜索引擎安装配置Head插件 3.Ela ...

随机推荐

  1. 日志框架之2 slf4j+logback实现日志架构 · 远观钱途

    如何从缤纷复杂的日志系统世界筛选出适合自己的日志框架以及slf4j+logback的组合美妙之处?此文可能有帮助 logback介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网 ...

  2. figure图像

    import matplotlib.pyplot as plt import numpy as np x=np.linspace(-3,3,50) y1=x*2+1 y2=x**2 plt.plot( ...

  3. 在没有APP的125年前 印度的外卖小哥是这样送餐

    说到印度,你想到的是什么?咖喱.歌舞剧.开挂的火车?通通不是,我今天要说的是他们的外卖小哥,在印度如同"神"一般的存在.其实印度人不叫这批人为外卖小哥,而称他们为dabbawala ...

  4. CSRF之POST

    最近重温<白帽子讲web安全>一书,看到第4章CSRF的时候,发现有个错误的地方,第116页底部的代码中有个坑,那段代码是运行不了的.原因是在form表单中有个<input type ...

  5. 算发帖&mdash;&mdash;俄罗斯方块覆盖问题一共有多少个解

    问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形.   那么一共可以有多少个解呢?(若通过旋转.翻转一个解而得到的新解,则两个解视为同一个解)   首先,求解的问题,已经在上一篇帖子里完成 算 ...

  6. 一篇文章带您读懂List集合(源码分析)

    今天要分享的Java集合是List,主要是针对它的常见实现类ArrayList进行讲解 内容目录 什么是List核心方法源码剖析1.文档注释2.构造方法3.add()3.remove()如何提升Arr ...

  7. PDF 相关操作

    去年一年偷了下懒, 博客写了一点就没写了, 还好一些大的flag完成了.  花了半年的空余时间, 培养了一门兴趣爱好.   自己在为人处世上还是不够圆滑啊, 也难怪.   自己当初选择走技术这条路的初 ...

  8. 奉上简单的.Net后端开发模板

    假定一个场景,开始做开发的你,领导走到你的面前说道:"小伙子,看了简历和最近的工作表现,很不错,现在交给一个任务,开发一个简单的CMS后端接口吧,前端有人配合你",当时你内心读白: ...

  9. C# 客户端内存优化分析

    背景概述 C# 开发客户端系统的时候,.net 框架本身就比较消耗内存资源,特别是xp 这种老爷机内存配置不是很高的电脑上运行,所以就需要进行内存上的优化,才能流畅的在哪些低端电脑上运行. 想要对C# ...

  10. 【从零单排HBase 01】从一无所知到5分钟快速了解HBase

    最近公司正好准备投入HBase,因此做了一些基础学习准备,所以先暂时停止MySQL的更新,把HBase的学习心得跟大家分享一下,接下来一段时间都会发布HBase相关内容. 在学的过程中,发现跟MySQ ...