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

 

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

这是因为使用了Elasticsearch中默认的标准分词器,这个分词器在处理中文的时候会把中文单词切分成一个一个的汉字,因此引入中文的分词器就能解决这个问题。

本篇文章按照下面的内容进行描述:

  • 分词器的作用
  • 安装IK
  • 简单的测试
  • 模拟测试
  • 安装elasticsearch-analysis-pinyin
  • 简单的测试
  • 模拟测试

分词器的作用

分词顾名思义,就是把一句话分成一个一个的词。这个概念在搜索中很重要,比如 This is a banana. 如果按照普通的空格来分词,分成this,is,a,banana,的出来的a其实对我们并没有什么用处。因此需要注意下面的问题:

  • 1 区分停顿词(a,or,and这种都属于停顿词)
  • 2 大小写转换(Bananabanana)
  • 3 时态的转换....

具体的算法可以参考http://tartarus.org/~martin/PorterStemmer/,对照的词语可以参考这里http://snowball.tartarus.org/algorithms/porter/diffs.txt

相比中文,就复杂的度了。因为中文不能单纯的依靠空格,标点这种进行分词。就比如中华人民共和国国民,不能简单的分成一个词,也不能粗暴的分成中华人民共和国国民人民中华这些也都算一个词!

因此常见的分词算法就是拿一个标准的词典,关键词都在这个词典里面。然后按照几种规则去查找有没有关键词,比如:

  • 正向最大匹配(从左到右)
  • 逆向最大匹配(从右到左)
  • 最少切分
  • 双向匹配(从左扫描一次,从右扫描一次)

IK,elasticsearch-analysis-ik提供了两种方式,ik_smart就是最少切分,ik_max_word则为细粒度的切分(可能是双向,没看过源码)

了解了分词器的背景后,就可以看一下如何在Elasticsearch重安装分词器了。

安装IK

github中下载相应的代码,比如我的最新版本2.4.0就没有对应的ik版本,不用担心,只需要修改pom.xml就可以了:

<properties>
<!-- 这里的版本号,修改成你对应的版本就行了。
不过最好不要跨度太大,相近的版本可能没有问题,但是跨度太大的版本,这样做就不保证好使了-->
<elasticsearch.version>2.4.0</elasticsearch.version>
<maven.compiler.target>1.7</maven.compiler.target>
<elasticsearch.assembly.descriptor>${project.basedir}/src/main/assemblies/plugin.xml</elasticsearch.assembly.descriptor>
<elasticsearch.plugin.name>analysis-ik</elasticsearch.plugin.name>
<elasticsearch.plugin.classname>org.elasticsearch.plugin.analysis.ik.AnalysisIkPlugin</elasticsearch.plugin.classname>
<elasticsearch.plugin.jvm>true</elasticsearch.plugin.jvm>
<tests.rest.load_packaged>false</tests.rest.load_packaged>
<skip.unit.tests>true</skip.unit.tests>
<gpg.keyname>4E899B30</gpg.keyname>
<gpg.useagent>true</gpg.useagent>
</properties>

下载后,执行mvn package,进行打包:

├─config
├─src
└─target
├─archive-tmp
├─classes
├─generated-sources
├─maven-archiver
├─maven-status
├─releases
│ └─elasticsearch-analysis-ik-1.9.5.zip
└─surefire

编译完成后,可以在target/releases目录下找到对应的zip包。

解压zip包,复制到elasticsearch-root-path/plugins/ik下即可。

[root@hadoop-master ik]# ll
total 1428
-rw-r--r-- 1 root root 263965 Sep 26 15:03 commons-codec-1.9.jar
-rw-r--r-- 1 root root 61829 Sep 26 15:03 commons-logging-1.2.jar
drwxr-xr-x 3 root root 4096 Sep 26 16:11 config
-rw-r--r-- 1 root root 56023 Sep 26 15:03 elasticsearch-analysis-ik-1.9.5.jar
-rw-r--r-- 1 root root 736658 Sep 26 15:03 httpclient-4.5.2.jar
-rw-r--r-- 1 root root 326724 Sep 26 15:03 httpcore-4.4.4.jar
-rw-r--r-- 1 root root 2666 Sep 26 15:03 plugin-descriptor.properties
[root@hadoop-master ik]# pwd
/usr/elk/elasticsearch-2.4.0/plugins/ik

拷贝后,重启elasticsearch就可以使用分词器了。

最简单的测试

这里使用_analyze api对中文段落进行分词,测试一下:

GET _analyze
{
"analyzer":"ik_max_word",
"text":"中华人民共和国国歌"
}

可以看到ik尽可能多的切分的单词:

{
"tokens": [
{
"token": "中华人民共和国",
"start_offset": 0,
"end_offset": 7,
"type": "CN_WORD",
"position": 0
},
{
"token": "中华人民",
"start_offset": 0,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
},
{
"token": "中华",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 2
},
{
"token": "华人",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 3
},
{
"token": "人民共和国",
"start_offset": 2,
"end_offset": 7,
"type": "CN_WORD",
"position": 4
},
{
"token": "人民",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 5
},
{
"token": "共和国",
"start_offset": 4,
"end_offset": 7,
"type": "CN_WORD",
"position": 6
},
{
"token": "共和",
"start_offset": 4,
"end_offset": 6,
"type": "CN_WORD",
"position": 7
},
{
"token": "国",
"start_offset": 6,
"end_offset": 7,
"type": "CN_CHAR",
"position": 8
},
{
"token": "国歌",
"start_offset": 7,
"end_offset": 9,
"type": "CN_WORD",
"position": 9
}
]
}

如果使用ik_smart,则会尽可能少的返回词语:

{
"tokens": [
{
"token": "中华人民共和国",
"start_offset": 0,
"end_offset": 7,
"type": "CN_WORD",
"position": 0
},
{
"token": "国歌",
"start_offset": 7,
"end_offset": 9,
"type": "CN_WORD",
"position": 1
}
]
}

模拟测试

我这里直接在elastic Sense中进行测试的(强烈推荐这个插件,非常好用,不过输入中文的时候,有点BUG)

第一步,创建一个空的索引

PUT test
{ }

如果你用的是curl,可以执行curl -XPUT localhost:9200/test

第二步,设置映射类型

POST test/test/_mapping
{
"test": {
"_all": {
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word",
"term_vector": "no",
"store": "false"
},
"properties": {
"content": {
"type": "string",
"store": "no",
"term_vector": "with_positions_offsets",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word",
"include_in_all": "true",
"boost": 8
}
}
}
}

上面的命令,是定义test索引下test类型的映射。其中定义了_all字段的分析方法,以及content属性的分析方法。

这里介绍下什么是_all字段,其实_all字段是为了在不知道搜索哪个字段时,使用的。es会把所有的字段(除非你手动设置成false),都放在_all中,然后通过分词器去解析。当你使用query_string的时候,默认就在这个_all字段上去做查询,而不需要挨个字段遍历,节省了时间。

properties中定义了特定字段的分析方式。在上面的例子中,仅仅设置了content的分析方法。

  • type,字段的类型为string,只有string类型才涉及到分词,像是数字之类的是不需要分词的。
  • store,定义字段的存储方式,no代表不单独存储,查询的时候会从_source中解析。当你频繁的针对某个字段查询时,可以考虑设置成true。
  • term_vector,定义了词的存储方式,with_position_offsets,意思是存储词语的偏移位置,在结果高亮的时候有用。
  • analyzer,定义了索引时的分词方法
  • search_analyzer,定义了搜索时的分词方法
  • include_in_all,定义了是否包含在_all字段中
  • boost,是跟计算分值相关的。

设置完成后,添加一个文档

POST test/test/1
{
"test":"美国留给伊拉克的是个烂摊子吗"
} POST test/test/2
{
"content":"公安部:各地校车将享最高路权吗"
} POST test/test/3
{
"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"
} POST test/test/4
{
"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
}

最后,执行查询进行测试

GET test/_search
{
"query" : { "term" : { "content" : "中国" }},
"highlight" : {
"pre_tags" : ["<tag1>", "<tag2>"],
"post_tags" : ["</tag1>", "</tag2>"],
"fields" : {
"content" : {}
}
}
}

得到返回结果:

{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1.5,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "4",
"_score": 1.5,
"_source": {
"content": "中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
},
"highlight": {
"content": [
"<tag1>中国</tag1>驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
]
}
},
{
"_index": "test",
"_type": "test",
"_id": "3",
"_score": 0.53699243,
"_source": {
"content": "中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"
},
"highlight": {
"content": [
"中韩渔警冲突调查:韩警平均每天扣1艘<tag1>中国</tag1>渔船"
]
}
}
]
}
}

安装elasticsearch-analysis-pinyin分词器

pinyin分词器可以让用户输入拼音,就能查找到相关的关键词。比如在某个商城搜索中,输入shuihu,就能匹配到水壶。这样的体验还是非常好的。

pinyin分词器的安装与IK是一样的,这里就省略掉了。下载的地址参考github.

这个分词器在1.8版本中,提供了两种分词规则:

  • pinyin,就是普通的把汉字转换成拼音;
  • pinyin_first_letter,提取汉字的拼音首字母

简单的测试

首先创建索引,并创建分词器:

PUT medcl
{
"index" : {
"analysis" : {
"analyzer" : {
"pinyin_analyzer" : {
"tokenizer" : "my_pinyin",
"filter" : "word_delimiter"
}
},
"tokenizer" : {
"my_pinyin" : {
"type" : "pinyin",
"first_letter" : "none",
"padding_char" : " "
}
}
}
}
}

然后使用analyze api,进行测试

GET medcl/_analyze
{
"text":"刘德华",
"analyzer":"pinyin_analyzer"
}

可以得到结果:

{
"tokens": [
{
"token": "liu",
"start_offset": 0,
"end_offset": 3,
"type": "word",
"position": 0
},
{
"token": "de",
"start_offset": 0,
"end_offset": 3,
"type": "word",
"position": 1
},
{
"token": "hua",
"start_offset": 0,
"end_offset": 3,
"type": "word",
"position": 2
}
]
}

如果分词器设置为pinyin_first_letter,则分析的结果为:

{
"tokens": [
{
"token": "ldh",
"start_offset": 0,
"end_offset": 3,
"type": "word",
"position": 0
}
]
}

模拟测试

如果索引已经存在,需要先关闭索引

POST medcl/_close
{ }

然后设置分词器配置

PUT medcl/_settings
{
"index" : {
"analysis" : {
"analyzer" : {
"pinyin_analyzer" : {
"tokenizer" : "my_pinyin",
"filter" : ["word_delimiter","nGram"]
}
},
"tokenizer" : {
"my_pinyin" : {
"type" : "pinyin",
"first_letter" : "prefix",
"padding_char" : " "
}
}
}
}
}

打开索引

POST medcl/_open
{ }

定义映射类型

POST medcl/folks/_mapping
{
"folks": {
"properties": {
"name": {
"type": "multi_field",
"fields": {
"name": {
"type": "string",
"store": "no",
"term_vector": "with_positions_offsets",
"analyzer": "pinyin_analyzer",
"boost": 10
},
"primitive": {
"type": "string",
"store": "yes",
"analyzer": "keyword"
}
}
}
}
}
}

提交样例数据

POST medcl/folks/1
{
"name":"刘德华"
}

执行查询

GET medcl/folks/_search
{
"query": {"match": {
"name": "l d hua"
}}
}

这里搜liu de hua,ldh,l de hua都能匹配到,还是很强大滴。

得到结果

{
"took": 7,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 7.408082,
"hits": [
{
"_index": "medcl",
"_type": "folks",
"_id": "1",
"_score": 7.408082,
"_source": {
"name": "刘德华"
}
}
]
}
}

参考

 
分类: Elasticsearch

Elasticsearch IK+pinyin的更多相关文章

  1. (转)Elasticsearch 5 Ik+pinyin分词配置详解

    今天以这篇文章结束同城旅游网的面试,正好面试官也问到站内检索,可以尝试一下这篇文章介绍的方法.Elasticsearch 5 Ik+pinyin分词配置详解

  2. Elasticsearch 5 Ik+pinyin分词配置详解

    版权声明:本文为博主原创文章,地址:http://blog.csdn.net/napoay,转载请留言. 一.拼音分词的应用 拼音分词在日常生活中其实很常见,也许你每天都在用.打开淘宝看一看吧,输入拼 ...

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

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

  4. 聊聊 elasticsearch 之分词器配置 (IK+pinyin)

    系统:windows 10 elasticsearch版本:5.6.9 es分词的选择 使用es是考虑服务的性能调优,通过读写分离的方式降低频繁访问数据库的压力,至于分词的选择考虑主要是根据目前比较流 ...

  5. Elasticsearch:Pinyin 分词器

    Elastic的Medcl提供了一种搜索Pinyin搜索的方法.拼音搜索在很多的应用场景中都有被用到.比如在百度搜索中,我们使用拼音就可以出现汉字: 对于我们中国人来说,拼音搜索也是非常直接的.那么在 ...

  6. jar hell & elasticsearch ik 版本问题

    想给es 安装一个ik 的插件, 我的es 是 2.4.0, 下载了一个版本是 1.9.5, [2016-10-09 16:56:26,248][INFO ][node ] [node-2] init ...

  7. ElasticSearch ik分词安装

    1.下载对应版本的ES ik分词 https://github.com/medcl/elasticsearch-analysis-ik/releases 2.解压elasticsearch-analy ...

  8. 使用 Elasticsearch ik分词实现同义词搜索(转)

    1.首先需要安装好Elasticsearch 和elasticsearch-analysis-ik分词器 2.配置ik同义词 Elasticsearch 自带一个名为 synonym 的同义词 fil ...

  9. elasticsearch ik中文分词器安装

    特殊说明:灰色文字用来辅助理解的. 安装IK中文分词器 我在百度上搜索了下,大多介绍的都是用maven打包下载下来的源码,这种方法也行,但是不够方便,为什么这么说? 首先需要安装maven吧?其次需要 ...

随机推荐

  1. python根据关键字以及id值爬取图虫网上高质量大图

    import requests import re import os import time print("ready....") def downPic(dirs, keywo ...

  2. JSP(一):初识JSP

    在Servlet中,我们多次用到了jsp页面,今天就来仔细聊聊JSP. 一.概念 JSP全名是Java Server Pages,可理解为Java服务端页面,是一种动态网页开发技术,其本质是一个简化的 ...

  3. 《Java大学教程》—第18章 高级图形编程

    自测题:1.    在图形应用程序中为用户提供选择的多种方式:P433下拉菜单(pull-down menu).弹出式菜单(pop-up menu).对话框窗口(dialogue window).单选 ...

  4. python 基本运算符

    一.格式化输出 简易名片的制作 name="小龙女" phone=15464623646 firm="神雕侠侣" pro="神仙姐姐" pr ...

  5. 从Hadoop到Spark的架构实践

    当下,Spark已经在国内得到了广泛的认可和支持:2014年,Spark Summit China在北京召开,场面火爆:同年,Spark Meetup在北京.上海.深圳和杭州四个城市举办,其中仅北京就 ...

  6. HBase1.0.1.1 API与原来有所不同

    package com.felix.hbaseapi_test; /* 这是旧版的 API操作 */ public class hbaseapifelix { public static final ...

  7. 关于折半法查找的一些总结以及ArrayList类的总结

    一.折半法查找的总结(这算法很好理解,但我花了好久琢磨他有啥用.....) 1.实际意义 折半法查找主要是为了能够很快在一个数组中找出我们所需要的那个元素,与往常我们通过一个一个比较的方法不同,折半法 ...

  8. 为什么二流程序员都喜欢黑php?

    为什么二流程序员都喜欢黑php? 为什么程序员都喜欢黑php?这个嘛!你骂一句php是垃圾试试,保准php程序员不揍扁你!这就好像自己的母校,纵然有很多不好的地方,但是只允许自己调侃,不允许外人骂半句 ...

  9. MySql Undo Redo

    Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomicity) ...

  10. 11g SPA (sql Performance Analyze) 进行升级测试

    注;转自http://ju.outofmemory.cn/entry/77139 11G的新特性SPA(SQL Performance Analyze)现在被广泛的应用到升级和迁移的场景.当然还有一些 ...