Elasticsearch中使用ik分词器 JAVA api
一、Elasticsearch分词
在elasticsearch自带的分词器中,对中文分词是支持的,只是所有的分词都是按照单字进行分词的,例如所带的标准的分词器standard分词器,可以按照如下的方式查询是如何进行分词的
- http://localhost:9200/iktest/_analyze?pretty&analyzer=standard&text=中华人民共和国
上述例子使用的是standard进行分词,分词的结果如下:
- {
- "tokens" : [ {
- "token" : "中",
- "start_offset" : 0,
- "end_offset" : 1,
- "type" : "<IDEOGRAPHIC>",
- "position" : 0
- }, {
- "token" : "华",
- "start_offset" : 1,
- "end_offset" : 2,
- "type" : "<IDEOGRAPHIC>",
- "position" : 1
- }, {
- "token" : "人",
- "start_offset" : 2,
- "end_offset" : 3,
- "type" : "<IDEOGRAPHIC>",
- "position" : 2
- }, {
- "token" : "民",
- "start_offset" : 3,
- "end_offset" : 4,
- "type" : "<IDEOGRAPHIC>",
- "position" : 3
- }, {
- "token" : "共",
- "start_offset" : 4,
- "end_offset" : 5,
- "type" : "<IDEOGRAPHIC>",
- "position" : 4
- }, {
- "token" : "和",
- "start_offset" : 5,
- "end_offset" : 6,
- "type" : "<IDEOGRAPHIC>",
- "position" : 5
- }, {
- "token" : "国",
- "start_offset" : 6,
- "end_offset" : 7,
- "type" : "<IDEOGRAPHIC>",
- "position" : 6
- } ]
- }
二、ik分词器的安装
ik分词器是一款在使用es的时候常用的分词器,只要在github上进行下载即可,下载地址如下
- https://github.com/medcl/elasticsearch-analysis-ik/releases
- IK version ES version
- master 2.1.1 -> master
- 1.7.0 2.1.1
- 1.6.1 2.1.0
- 1.5.0 2.0.0
- 1.4.1 1.7.2
- 1.4.0 1.6.0
- 1.3.0 1.5.0
- 1.2.9 1.4.0
- 1.2.8 1.3.2
- 1.2.7 1.2.1
- 1.2.6 1.0.0
- 1.2.5 0.90.x
- 1.1.3 0.20.x
- 1.1.2 0.19.x
- 1.0.0 0.16.2 -> 0.19.0
下载完成之后,解压,然后使用mvn package进行打包,此处需要安装maven,如何安装请自行百度
打包完成之后,会出现 target/releases/elasticsearch-analysis-ik-{version}.zip
将zip文件拷贝到es所在目录下的/plugins/ik
对zip文件进行解压,解压完成之后需要修改plugin-descriptor.properties文件,将其中的java版本,以及es版本号均改为你所使用的版本号,即完成ik分词器的安装
三、对ik分词器的效果进行检测
安装完成时候,使用之前的命令进行检测,因为ik分词器分为两种分词方法,一种是最大切分,一种是全切分,对应的名字为ik_smart,ik_max_word,其中smart的切分更加符合日常的用于,max_word的切分会更加的细致,如github上面所讲述的,下面对于给定的句子我们进行一个检测,句子为:中华人民共和国
ik_samrt切分结果:
- http://localhost:9200/iktest/_analyze?pretty&analyzer=ik_smart&text=中华人民共和国
- {
- "tokens" : [ {
- "token" : "中华人民共和国",
- "start_offset" : 0,
- "end_offset" : 7,
- "type" : "CN_WORD",
- "position" : 0
- } ]
- }
ik_max_word切分:
- http://localhost:9200/iktest/_analyze?pretty&analyzer=ik_max_word&text=中华人民共和国
- {
- "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
- } ]
- }
四、关于两种不同分词的用处以及区别:
1、使用方面的不同
其中我们在做索引的时候,希望能将所有的句子切分的更详细,以便更好的搜索,所以ik_max_word更多的用在做索引的时候,但是在搜索的时候,对于用户所输入的query(查询)词,我们可能更希望得比较准确的结果,例如,我们搜索“无花果”的时候,更希望是作为一个词进行查询,而不是切分为"无",“花”,“果”三个词进行结果的召回,因此ik_smart更加常用语对于输入词的分析
2、效率方面的不同
ik_max_word分词相对来说效率更加迅速,而ik_smart的效率比不上ik_max_word(个人做索引的时候将两种分词器进行尝试得出的结果,有误的话,望指正)
五、java api实现指定分词器
实际应用的时候,我们可能都是在程序里面来实现指定分词器的,而上面所讲述的均为直接在网页进行查看的结果,那么如何指定分词器呢?如何用java代码实现呢
经过查找,最终发现三种方法来指定分词器
(1)在构造mapping的时候对于字段进行指定
在构造mapping的时候,我们可以对于指定的字段使用指定的分词器,所使用的java 代码如下所示:
- private XContentBuilder createIKMapping(String indexType) {
- XContentBuilder mapping = null;
- try {
- mapping = XContentFactory.jsonBuilder().startObject()
- // 索引库名(类似数据库中的表)
- .startObject(indexType).startObject("properties")
- .startObject("product_name").field("type", "string")
- .field("analyzer","ik").field("search_analyzer","ik_smart").endObject()
- .startObject("title_sub").field("type", "string")
- .field("analyzer","ik").field("search_analyzer","ik_smart").endObject()
- .startObject("title_primary").field("type", "string")
- .field("analyzer","ik").field("search_analyzer","ik_smart").endObject()
- .startObject("publisher").field("type", "string")
- .field("analyzer","ik").field("search_analyzer","ik_smart").endObject()
- .startObject("author_name").field("type", "string")
- .field("analyzer","ik").field("search_analyzer","ik_smart").endObject()
- //.field("boost",100).endObject()
- // 姓名
- //.startObject("name").field("type", "string").endObject()
- // 位置
- //.startObject("location").field("type", "geo_point").endObject()
- //.endObject().startObject("_all").field("analyzer","ik").field("search_analyzer","ik").endObject().endObject().endObject();
- .endObject().endObject().endObject();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return mapping;
- }
(2)对于所有的字段进行指定
此方法未经测试通过,只是知道有这种方法,通过的同学麻烦跟我说下哈,感激不尽
如果ik下面的介绍一样,所使用的dsl语句如下所示:
- curl -XPOST http://localhost:9200/index/fulltext/_mapping -d'
- {
- "fulltext": {
- "_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
- }
- }
- }
- }'
- private XContentBuilder createIKMapping(String indexType) {
- XContentBuilder mapping = null;
- try {
- mapping = XContentFactory.jsonBuilder().startObject()
- // 索引库名(类似数据库中的表)
- .startObject(indexType).startObject("properties") .endObject()
- .startObject("_all").field("analyzer","ik").field("search_analyzer","ik").endObject()
- .endObject().endObject();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return mapping;
- }
(3)、在setting的时候进行设置
经过看书得知,在setting的时候可以直接设置analyzer,如图所示:
此种方法未经测试,只是可以确定可行性。
转自:http://blog.****.net/molong1208 https://blog.****.net/molong1208/article/details/50557253