给IKAnalyzer分词加多自定义扩充词库,IK自动热更新原理与落到实处

IKAnalyzer是壹款不错的华语分词组件,其置于了词库,内置的词库在其jar包Nene嵌,所以您不会看到内置词库。
大家也能够给IKAnalyzer加多自定义词库,增加的点子求证如下:

一、热更新原理

  elasticsearch开启加载外部词典功功效后,会每60s区间进行刷新字典。具体原理代码如下所示:

public void loadDic(HttpServletRequest req,HttpServletResponse response){
    String eTag =req.getParameter("If-None-Match");
    try {
        OutputStream out= response.getOutputStream();
        List<String> list=new ArrayList<String>();
        list.add("中华人民共和国");
        list.add("我爱你爱我");
        String oldEtag = list.size() + "";
        StringBuffer sb=new StringBuffer();
        if (oldEtag != eTag) {
            for (String str : list) {
                if(StringUtils.isNotBlank(str)){
                    sb.append("\r\n");
                }
                sb.append(str+"\r\n");
            }
        }
        String data=sb.toString();

        response.setHeader("Last-Modified", String.valueOf(list.size()));
        response.setHeader("ETag",String.valueOf(list.size()));
        response.setContentType("text/plain; charset=gbk");
        out.write(data.getBytes());
        out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

席卷内容:

IK分词组件的丰盛和布局

目录建设构造及高亮寻找示例

增添自定义分词的测试

首先必要在项目中新建1个词库配置文件,要放在能源文件的跟目录,文件名叫固定的IKAnalyzer.cfg.xml,在文书中增添如下内容:

贰、配置表明

  大家厂家以及用户常用的分词器为 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">custom/mydict.dic;custom/single_word_low_freq.dic</entry>  
     <!--用户可以在这里配置自己的扩展停止词字典-->  
    <entry key="ext_stopwords">custom/ext_stopword.dic</entry>  
    <!--用户可以在这里配置远程扩展字典 -->  
    <entry key="remote_ext_dict">location</entry>  
    <!--用户可以在这里配置远程扩展停止词字典-->  
    <entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>  
</properties>

  热更新 IK 分词使用方法,最近该插件援救热更新 IK 分词,通过上文在 IK
配置文件中关系的如下配置

<!--用户可以在这里配置远程扩展字典 -->  
<entry key="remote_ext_dict">location</entry>  
<!--用户可以在这里配置远程扩展停止词字典-->  
<entry key="remote_ext_stopwords">location</entry> 

  当中 location 是指三个 url,比如

  该 http 请求要求回到两个尾部(header)

  1. 一个是 Last-Modified,

  2. 一个是 ETag

  那贰者都是字符串类型,只要有三个爆发变化,该插件就能去抓取新的分词进而更新词库。
  该 http 请求重返的内容格式是单排3个分词,换行符用 \n 即可。

  满意上边两点须要就足以落成热更新分词了,无需重启 ES
实例。还须要留意的是赢得词典的url,必须帮助head访问

上边自身做的走访远程扩张词典的web api 服务接口(这一步能够一向忽略,看第多个就可以,这里只是想证明也得以应用下边这种措施)

[HttpHead, HttpGet, HttpPost]  
public async Task<HttpResponseMessage> GetDictionary(string path)  
{  
    var response = this.Request.CreateResponse(HttpStatusCode.OK);  
    var content = File.ReadAllText(path);  
    response.Content = new StringContent(content, Encoding.UTF8);  
    response.Headers.Age = TimeSpan.FromHours(1);  
    response.Headers.ETag = EntityTagHeaderValue.Parse($"\"{content.ToMD5()}\"");  
    return response;  
}

版本: 

ES – 2.4.5, IK – 1.10.5 
ps: 5.0的版本, 配置和验证代码都不是太雷同, 以下应该只适用于二.x版本

IK Analyzer是四个开源的, 基于java语言开采的轻量级的汉语分词工具包,
应该是时下比较公认的适合ES的中文分词方案,
因为它暗中同意达成了针对性luence的优化. 下边会先介绍安装配置形式, 再介绍应用. 

Analyzer:ik_smart,ik_max_word, Tokenizer:ik_smart,ik_max_word

此间假如大家早已配备好了ES集群 [那么些实在很简短,
因为es的暗中认可配置就曾经很好]

推荐应用rpm的装置方式:

图片 1

壹 下载对应的IK版本
https://github.com/medcl/elasticsearch-analysis-ik

图片 2

二 下载pre-build, 可能电动编写翻译

工程是pom, 须要设置maven,
git clone
cd elasticsearch-analysis-ik
git checkout tags/{version}
mvn clean
mvn compile
mvn package

本人实在是平素下载的pre-build,
elasticsearch-analysis-ik-1.10.5.zip

三 配置

First, 解压elasticsearch-analysis-ik-一.10.5.zip,
拷贝到plugins/analysis-ik下, 假如是rpm安装的,
则对应的目录为/usr/share/elasticsearch/plugins/analysis-ik

图片 3

**Second**,
修改elasticsearch的安顿文件,内定IK为分词工具。张开/etc/elasticsearch/elasticsearch.yml,
最终加多 [那不该也不用做, 作者有多少个节点没做也是没难题的,
所以官方文书档案是对的
]:

*    index.analysis.analyzer.default.type: ik*

Last, 词典.
看到众多少人写的安装携带都关涉了将词典拷贝到es的config目录,
亲测这一步是无需的. 

验证: 最棒恐怕用浏览器直接表明, 命令行的话还亟需管理编码难点

(即使, 官方表达说在有些索引下调用接口测试, 如若是单点测试的话,
其实没什么差别, 可是倘若集群的话钦赐的index决定了在哪个节点执行)

图片 4

analyzer近日帮衬二种, ik_max_word和ik_smart, 他们的界别在于分词的粒度

*ik_max_word: “笔者是神州人” –> “小编, 中夏族民共和国人, 中华人民共和国, 国人”
*

*ik_smart: “小编是华夏人” –> “笔者, 中华夏族民共和国人”*

合法文书档案分词测试表明: 

PS: 个人相比较欣赏kopf这么些插件, 简洁, 清晰, 

1 创建ik_index

PUT

2 创建mapping

POST -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}}
}}’

3 index some docs

curl -XPOST
-d'{“content”:”U.S.A.留下伊拉克的是个烂摊子吗”}’

curl -XPOST
-d'{“content”:”公安厅:外市校车将享最高路权”}’

curl -XPOST
-d'{“content”:”中国和南朝鲜渔警争持调查:韩警平均每一日扣一艘中夏族民共和国捕鱼船”}’

curl -XPOST
-d'{“content”:”中华夏族民共和国驻布鲁塞尔领馆遭亚洲人后裔男人枪击 嫌嫌犯已自首”}’

4 query with highlighting

curl -XPOST   -d’
{
“query” :{ “term” : { “content” : “中国” }},
“highlight” : {“pre_tags” : [“”, “”],
“post_tags” : [“”, “”],
“fields” : {“content” : {}}}
}’

result:

图片 5

<?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">cn/outofmemory/my.dic;cn/outofmemory/mine.dic;</entry> 
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">cn/outofmemory/stopword.dic</entry> 
</properties>

三、汤姆cat 服务器自动更新

 1、部署http服务

  在那使用 tomcat八 作为 web 容器,先下载一个tomcat捌.5.1陆,然后上传到某1台服务器上(1九2.168.80.十0)。

  再实施以下命令

tar -zxvf apache-tomcat-8.5.16.tar.gz
cd apache-tomcat-8.5.16/webapp/ROOT
vim hot_ext.dic
智能移动机器人
vim hot_stopwords.dic
项目

  之后验证一下以此文件是或不是能够平常访问   http://192.168.80.100:8080/hot.dic

  2、修改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">custom/mydict.dic;custom/single_word_low_freq.dic</entry>  
     <!--用户可以在这里配置自己的扩展停止词字典-->  
    <entry key="ext_stopwords">custom/ext_stopword.dic</entry>  
    <!--用户可以在这里配置远程扩展字典 -->  
    <entry key="remote_ext_dict">http://192.168.80.100:8080/hot_ext.dic</entry>  
    <!--用户可以在这里配置远程扩展停止词字典-->  
    <entry key="remote_ext_stopwords">http://192.168.80.100:8080/hot_stopwords.dic</entry>  
</properties>

 3、验证

  重启es,会看到如下日志消息,表达远程的词典加载成功了。

  图片 6

  在浏览器中输入如下命令:

  不荒谬情状下会分出很数十次,这一次发掘只有那一个词,不会被分词,表明刚刚配置远程的词库生效了,那么我们再换四个:法国首都灰霾,经常处境下或然会被分成五个词:法国首都、阴霾,借使笔者一直改造tomcat 下的 hot_ext.dic
词库文件,扩大4人命关天词:香港(Hong Kong)阴霾,文件保留之后,查看es的日志会看到如下日志消息:

  图片 7

  此时,再进行上面发号施令查看分词效果:

  结果正是唯有八个词,不会被分词了。

  到这甘休,能够完成动态增加自定义词库完结词库热更新。~~

  

Dictionary Configuration:

IKAnalyzer.cfg.xml can be located
at{conf}/analysis-ik/config/IKAnalyzer.cfg.xml or
{plugins}/elasticsearch-analysis-ik-*/config/IKAnalyzer.cfg.xml

图片 8

热更新 IK
分词使用方法

当前该插件帮助热更新 IK 分词,通过上文在 IK 配置文件中关系的如下配置

图片 9

中间location是指一个url,比如

  1. 该 http
    请求必要重返八个尾部(header),1个是Last-Modified,二个是ETag,那两边都以字符串类型,只要有二个产生变化,该插件就可以去抓取新的分词进而更新词库。

  2. 该 http 请求重临的从头到尾的经过格式是单排2个分词,换行符用\n即可。

知足上边两点供给就足以完毕热更新分词了,无需重启 ES 实例。

能够将需自动更新的热词放在一个 UTF-捌 编码的 .txt 文件里,放在 nginx
或其余简易 http server 下,当 .txt 文件修改时,http server
会在客户端请求该文件时自动再次回到相应的 Last-Modified 和
ETag。可以此外做2个工具来从职业系统提取相关词汇,并更新那些 .txt
文件。

留意八个entry节点中分别安插了增添词典,和扩展的stopwords,
四个词典之间用英文半角分号;分割。

拉长分词测试:

同盟社名为小鱼易连, 小鱼是能够被识别成一个词的,
可是易连就不认了, 效果如下

localhost:9200/_analyze?analyzer=ik&pretty=true&text=小鱼易连

图片 10

这可不是我盼望的, 用户在搜产品文档的时候输入“易连”找不到结果可丰硕,
其实相当的粗略, 有二种艺术:

三个是基于地点提到的热更新方法, 通过插件自动抓取扩张词典的变化更新词库. 

除此以外三个, 我们能够长足验证, 通过转移config/custom下的mydict.dic,
在文书结尾增加”易连”就能够, 可是须要重启服务加载词库.效果如下:

图片 11

能够看到, 文档陆的得分显然不仅文档伍, 您能够用伍分钟思考一下为啥.

即时只寻找”易连”, 文书档案六同样相关度越来越高

图片 12

答案是, 文书档案6在目录时, 增加了”小鱼易连”那一个分词, 关于这么些评分,
因为会做二个站内搜索效用, 未来会单独分享2次, 包蕴高亮的介绍.

然后是加多自定义扩张词库,须要放在对应的能源文件目录下,词库的格式是单排2个词,举个例子:

马云
马化腾
内存溢出

下边是1段测试分词的java代码:

package cn.outofmemory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

public class App {
    public static void main(String[] args) {
        String str = "马云和马化腾是两个牛人";

        IKAnalysis(str);
    }

    public static String IKAnalysis(String str) {
        StringBuffer sb = new StringBuffer();
        try {
            byte[] bt = str.getBytes();
            InputStream ip = new ByteArrayInputStream(bt);
            Reader read = new InputStreamReader(ip);
            IKSegmenter iks = new IKSegmenter(read, false);
            Lexeme t;
            while ((t = iks.next()) != null) {
                sb.append(t.getLexemeText() + " , ");
            }
            sb.delete(sb.length() - 1, sb.length());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(sb.toString());
        return sb.toString();
    }
}

运维之后能够看看IKAnalyzer的分词结果。

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注