Elasticsearch IK中文分词插件和添加词库

ik插件地址:

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

下载对应的版本号,插件的版本号是跟Elasticsearch的版本号必须相匹配才可使用。

cd your-es-root/plugins/ && mkdir ik

unzip plugin to folder your-es-root/plugins/ik

重启Elasticsearch无报错则插件安装成功

使用:

添加索引并设置分词模式

$params = [
            'index' => 'my_index',
            'body' => [
                'settings' => [
                    // 'number_of_shards' => 2,
                    // 'number_of_replicas' => 0
                    "analysis" => [
                        "analyzer" => [
                            "ik" => [
                                "tokenizer" => "ik_max_word"
                            ]
                        ]
                    ]
                ],
                'mappings' => [ // 映射是另外一个嵌套在body中的顶级元素,包含各种类型的映射
                    'properties' => [
                        "title"=> [
                            "type"=> "text",
                            "analyzer"=> "ik_max_word"
                        ],
                        "content"=> [
                            "type"=> "text",
                            "analyzer"=> "ik_max_word",
                            "search_analyzer"=> "ik_smart"
                        ]
                    ]
                ]
            ]
        ];
        $response = $client->indices()->create($params);
        print_r($response);
添加文档:
$params = [
            'index' => 'my_index',
            'type' => '_doc',
            'id' => '20',
            'body' => ['title' => '大考卷今天完成',"content"=>"张大仙和锅老师是朋友"]
        ];
        $response = $client->index($params);
        print_r($response);
查看文档对某字段的分词情况:
curl http://127.0.0.1:9200/my_index/_doc/12/_termvectors?fields=content
以上命令表示查看my_index文档id为12的content字段的分词情况。
测试分词情况:
curl -H "Content-Type: application/json" -XGET http://127.0.0.1:9200/_analyze?pretty -d'{"analyzer":"ik_max_word","text":"一场高逼格盛宴"}'
以上表示以ik_max_word分词模式显示"一场高逼格盛宴"的分词信息。
自定义分词:
1.直接自定义分词字典,在Elasticsearch重启时直接加载使用,有新词添加时需要重启动才可生效。
2.热更新 IK 分词,使用HTTP形式返回分词,可动态添加和减少,分词产生变化后,当服务器加载了新 的分词后,此后添加的文档会使用新的分词进行内容分词,而之前的内容并不会自动进行分词。如需要对旧内容分词,需要自行处理。
配置词库:
IKAnalyzer.cfg.xml can be located at {conf}/analysis-ik/config/IKAnalyzer.cfg.xml or {plugins}/elasticsearch-analysis-ik-*/config/IKAnalyzer.cfg.xml
7.7.1版本中位置是在后者。
配置文件内容如下:
<?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>
第一行key="ext_dict"表示直接使用用户自定义词典,词典目录为:your-es-root/plugins/ik/config/custom/mydict.dic
第二行key="ext_stopwords" 表示本地的停用词典,配置跟第一行相同
第三行key="remote_ext_dict" 表示热更新分词,检测到新分词的后会使用新的分词
第四行key="remote_ext_stopwords" 表示热更新停用分词,跟第三行机制一样,热加载

PHP热更新分词使用:
修改remote_ext_dict的远程
<entry key="remote_ext_dict">http://www.laravel-test.com/ikWords</entry>
laravel:
public function ikWords()
    {
        $fileSize = 0;
        $filePath = storage_path('app/ik/ext_dict.txt');
        if (\file_exists($filePath)) {
            $content = file_get_contents($filePath);
            $fileSize = filesize($filePath);
        }
        $status = 200;
        $lastUpdateTime = '2020-06-20 22:21:12';
        return response($content)
            ->header('Last-Modified', $lastUpdateTime)
            ->header('Content-Length', $fileSize)
            ->setETag(md5('v02'))
            ;
    }
原生:
$content = "";

$dicFile = dirname(__FILE__).'/ik/ext_dict.txt';

if (file_exists($dicFile)) {
    $content = file_get_contents($dicFile);
}
$etag = md5('v22');
header('Last-Modified: Sun, 30 Apr 2017 14:19:55 GMT', true, 200);
header("ETag: W/\"$etag\"");
header("Content-Length: ".filesize($dicFile));
echo $content;
根据es热词更新机制,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
txt文件里的内容即为用户自定义分词,一个词一行。如下:
张大仙
锅老师

问题:
1.在使用热更分词时,填写热更新地址后,从es日志查看,地址已经load成功,但是对应的词典并没有加载进来。
 原因:返回内容没有header的Content-Length属性,原因可查看https://github.com/medcl/elasticsearch-analysis-ik/issues/689,
对Content-Length大于0才会进行处理。
 解决:添加Content-Length 的header属性