八.文档分词器及自定义分词案例(了解即可)
1.文档分析
文档分析包含下面的过程:
(1)将一块文本分成适合于倒排索引的独立的词条;
(2)将这些词条统一化为标准格式以提高它们的"可搜索性",或者recall分词器执行上面的工作。分析器实际上是将三个功能封装到了一个package里:
字符过滤器:
首先,字符串按顺序通过每个字符过滤器。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将&转化成and。
分词器:
其次,字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条。
Token过滤器:
最后,词条按照顺序通过每个token过滤器。这个过程可能会改变词条(例如,小写化,Quick),删除词条(例如,像a,and,the等无用词),或者增加词条(例如,像jump和leap这种同义词)。
2.内置分析器
内置分析器:
ES还附带了可以直接使用的预包装的分析器。接下来我们会列出最重要的分析器。为了证明它们的差异,我们看看每个分析器会从下面的字符串得到哪些词条。
"Set the shape to semi-transparent by calling set_trans(5)"
标准分析器:
标准分析器是ES默认使用的分词器。它是分析各种语言文本最常用的选择。它根据Unicode联盟定义的单词边界划分文本。删除绝对部分标点。最后将词条小写。所以它会分析出以下词条:
set,the,shape,to,semi,transparent,by,calling,set_trans,5
简单分析器:
简单分析器在任何不是字母的地方分隔文本,将词条小写。所以它会产生以下词条:
set,the,shape,to,semi,transparent,by,calling,set,trans
空格分析器:
空格分析器在空格的地方划分文本,所以它会产生以下词条:
Set,the,shape,to,semi-transparent,by,calling,set_trans(5)
语言分析器:
特定语言分析器可用于很多语言。它们可以考虑指定语言的特点。例如,英语分析器还附带了无用词(常用单词,例如and或者the,它们对相关性没有多少影响),它们会被删除。由于理解英语语法的规则,这个分词器可以提取英语单词的词干。所以英语分词器会产生下面的词条:
set,shape,semi,transpar,call,set_tran,5
注意看"transparent","calling"和"set_trans"已经变成词根格式。
3.分析器使用场景
当我们索引一个文档,它的全文域被分析成词条以用来创建倒排索引。但是,当我们在全文域搜索的时候,我们需要将字符串通过相同的分析过程,以保证我们搜索的词条格式与索引中的词条格式一致。
4.测试分析器-标准分析器(“standard”)
有些时候很难理解分词的过程和实际被存储到索引的词条,特别是你刚接触ES。为了理解发生了上面,你可以使用analyze API来看文本时如何被分析的。
在消息体里,指定分析器和要分析的文本:
curl -X GET/POST http://elk101.k8s.com:9200/_analyze
{
"analyzer": "standard",
"text":"My name is Jason Yin and I'm 18 years old!"
}
5.ES内置的中文分词并不友好
在消息体里,指定分析器和要分析的文本:
curl -X GET/POST http://elk101.k8s.com:9200/_analyze
{
"text":"我爱北京天安门"
}
6.中文分词器概述
中文分词的难点在于,在汉语中没有明显的词汇分界点,如在英语中,空格可以作为分隔符,如果分隔符不正确就会造成歧义。常用中文分词器有IK,jieba,THULAC等,推荐使用IK分词器。
"IK Analyzer"是一个开源的,基于Java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版本开始,IK Analyzer已经推出了3个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。
新版本的IK Analyzer 3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供对Lucene的默认优化实现。采用了特有的"正向迭代最新力度切分算法",具有"80万字/秒"的高速处理能力。
采用了多子处理器分析模式,支持: 英文字母(IP地址,Email,URL),数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇()姓名,地名处理等分词处理。优化的词典存储,更小的内存占用。
IK分词器Elasticsearch插件地址:
https://github.com/medcl/elasticsearch-analysis-ik
7.安装IK分词器插件
解压分词器到集群节点的插件目录即可:
[root@elk103.k8s.com ~]# mkdir -pv /k8s/softwares/elasticsearch/plugins/ikmkdir: 已创建目录 "/k8s/softwares/elasticsearch/plugins/ik"
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# ll /k8s/softwares/elasticsearch/plugins/ik/
总用量 0
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# ll
总用量 4400
-rw-r--r-- 1 root root 4504535 4月 30 21:14 elasticsearch-analysis-ik-7.12.1.zip
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# unzip elasticsearch-analysis-ik-7.12.1.zip -d /k8s/softwares/elasticsearch/plugins/ik/
Archive: elasticsearch-analysis-ik-7.12.1.zip
inflating: /k8s/softwares/elasticsearch/plugins/ik/elasticsearch-analysis-ik-7.12.1.jar
inflating: /k8s/softwares/elasticsearch/plugins/ik/httpclient-4.5.2.jar
inflating: /k8s/softwares/elasticsearch/plugins/ik/httpcore-4.4.4.jar
inflating: /k8s/softwares/elasticsearch/plugins/ik/commons-logging-1.2.jar
inflating: /k8s/softwares/elasticsearch/plugins/ik/commons-codec-1.9.jar
creating: /k8s/softwares/elasticsearch/plugins/ik/config/
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/extra_stopword.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/extra_single_word.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/main.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/surname.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/quantifier.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/preposition.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/extra_single_word_full.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/suffix.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/stopword.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/extra_single_word_low_freq.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/config/extra_main.dic
inflating: /k8s/softwares/elasticsearch/plugins/ik/plugin-descriptor.properties
inflating: /k8s/softwares/elasticsearch/plugins/ik/plugin-security.policy
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# ll /k8s/softwares/elasticsearch/plugins/ik/
总用量 1428
-rw-r--r-- 1 root root 263965 4月 25 16:22 commons-codec-1.9.jar
-rw-r--r-- 1 root root 61829 4月 25 16:22 commons-logging-1.2.jar
drwxr-xr-x 2 root root 299 4月 25 16:16 config
-rw-r--r-- 1 root root 54626 4月 30 21:14 elasticsearch-analysis-ik-7.12.1.jar
-rw-r--r-- 1 root root 736658 4月 25 16:22 httpclient-4.5.2.jar
-rw-r--r-- 1 root root 326724 4月 25 16:22 httpcore-4.4.4.jar
-rw-r--r-- 1 root root 1807 4月 30 21:14 plugin-descriptor.properties
-rw-r--r-- 1 root root 125 4月 30 21:14 plugin-security.policy
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]#
修改权限:
[root@elk103.k8s.com ~]# ll /k8s/softwares/elasticsearch/plugins/
总用量 0
drwxr-xr-x 3 root root 244 5月 25 17:32 ik
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# ll /k8s/softwares/elasticsearch/plugins/ik/
总用量 1428
-rw-r--r-- 1 root root 263965 4月 25 16:22 commons-codec-1.9.jar
-rw-r--r-- 1 root root 61829 4月 25 16:22 commons-logging-1.2.jar
drwxr-xr-x 2 root root 299 4月 25 16:16 config
-rw-r--r-- 1 root root 54626 4月 30 21:14 elasticsearch-analysis-ik-7.12.1.jar
-rw-r--r-- 1 root root 736658 4月 25 16:22 httpclient-4.5.2.jar
-rw-r--r-- 1 root root 326724 4月 25 16:22 httpcore-4.4.4.jar
-rw-r--r-- 1 root root 1807 4月 30 21:14 plugin-descriptor.properties
-rw-r--r-- 1 root root 125 4月 30 21:14 plugin-security.policy
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# chown -R k8s:k8s /k8s/softwares/elasticsearch/plugins/ik/
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# ll /k8s/softwares/elasticsearch/plugins/
总用量 0
drwxr-xr-x 3 k8s k8s 244 5月 25 17:32 ik
[root@elk103.k8s.com ~]#
[root@elk103.k8s.com ~]# ll /k8s/softwares/elasticsearch/plugins/ik/
总用量 1428
-rw-r--r-- 1 k8s k8s 263965 4月 25 16:22 commons-codec-1.9.jar
-rw-r--r-- 1 k8s k8s 61829 4月 25 16:22 commons-logging-1.2.jar
drwxr-xr-x 2 k8s k8s 299 4月 25 16:16 config
-rw-r--r-- 1 k8s k8s 54626 4月 30 21:14 elasticsearch-analysis-ik-7.12.1.jar
-rw-r--r-- 1 k8s k8s 736658 4月 25 16:22 httpclient-4.5.2.jar
-rw-r--r-- 1 k8s k8s 326724 4月 25 16:22 httpcore-4.4.4.jar
-rw-r--r-- 1 k8s k8s 1807 4月 30 21:14 plugin-descriptor.properties
-rw-r--r-- 1 k8s k8s 125 4月 30 21:14 plugin-security.policy
[root@elk103.k8s.com ~]#
# 重启服务使得配置生效:
[root@elk103.k8s.com ~]# su -l k8s
上一次登录:一 5月 24 10:59:06 CST 2021pts/0 上
[k8s@elk103.k8s.com ~]$
[k8s@elk103.k8s.com ~]$ jps
1571 Elasticsearch
2613 Jps
[k8s@elk103.k8s.com ~]$
[k8s@elk103.k8s.com ~]$ kill 1571
[k8s@elk103.k8s.com ~]$
[k8s@elk103.k8s.com ~]$ jps
2634 Jps
[k8s@elk103.k8s.com ~]$
[k8s@elk103.k8s.com ~]$ elasticsearch -d
[k8s@elk103.k8s.com ~]$
[k8s@elk103.k8s.com ~]$ jps
2770 Elasticsearch
2790 Jps
[k8s@elk103.k8s.com ~]$
8.测试IK分词器
curl -X GET/POST http://elk103.k8s.com:9200/_analyze
{
"analyzer": "ik_max_word",
"text":"我爱北京天安门"
}
curl -X GET/POST http://elk103.k8s.com:9200/_analyze
{
"analyzer": "ik_smart", // 会将文本做最粗粒度的拆分。
"text":"我爱北京天安门"
}
IK分词器说明:
"ik_max_word":
会将文本做最细粒度的拆分。
"ik_smart":
会将文本做最粗粒度的拆分。
温馨提示:
由于我将IK分词器只安装在了elk103节点上,因此我这里指定的ES节点就是按照的结点,生产环境中建议大家同步到所有节点。
9.自定义词汇
自定义词汇,文件名称可自行定义:
[oldboy@elk103.k8s.com ~]$ vim /oldboy/softwares/elasticsearch/plugins/ik/config/oldboy_custom.dic
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ cat /oldboy/softwares/elasticsearch/plugins/ik/config/oldboy_custom.dic
艾欧里亚
德玛西亚
[oldboy@elk103.k8s.com ~]$
将上面自定义词汇的文件名称写入IK分词器的配置文件中:
[oldboy@elk103.k8s.com ~]$ cat /oldboy/softwares/elasticsearch/plugins/ik/config/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>
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ vim /oldboy/softwares/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ cat /oldboy/softwares/elasticsearch/plugins/ik/config/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">oldboy_custom.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
[oldboy@elk103.k8s.com ~]$
重启ES服务使得配置生效:
[oldboy@elk103.k8s.com ~]$ jps
2770 Elasticsearch
2842 Jps
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ kill 2770
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ jps
2860 Jps
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ elasticsearch -d
[oldboy@elk103.k8s.com ~]$
[oldboy@elk103.k8s.com ~]$ jps
2996 Elasticsearch
3016 Jps
[oldboy@elk103.k8s.com ~]$
温馨提示:
(1)建议将IK分词器同步到集群的所有节点;
(2)修改"IKAnalyzer.cfg.xml"的配置文件时,我只修改了key="ext_dict"这一行配置项目,如下所示:
"<entry key="ext_dict">oldboy_custom.dic</entry>"
10.测试自定义词汇是否生效
curl -X GET/POST http://elk103.k8s.com:9200/_analyze
{
"analyzer":"ik_smart",
"text": "嗨,兄弟,你LOL哪个区的,我艾欧里亚和德玛西亚都有号"
}
11.为某个索引自定义分析器
虽然ElsticSearch带有一些现成的分词器,然而在分析器上ES真正的强大之处在于,你可以通过在一个合适你的特定数据的设置之中组合字符串过滤器,分词器,词汇单元过滤器来创建自定义的分词器。
在分析与分析器我们说过,一个分析器就是在一个package里面组合了三种函数的包装器,这三种函数按照顺序被执行:
字符过滤器:
用来整理一个尚未被分词的字符串。
例如,如果我们的文本时HTML格式的,它会包含像"<p>"或者"<div>"这样的HTML标签,这些标签时我们不想索引的。我们可以使用HTML清除字符过滤器来移除所有的HTML标签,并且像把"Á
"转换为相对应的Unicode字符A这样,转换HTML实体。一个分析器可能有0个或者多个字符过滤器。
分词器:
一个分词器必须有一个唯一的分词器。分词器把字符串分解成单个词条或者词汇单元。标准分析器里使用的标准分词器把一个字符串根据单词边界分解成单个词条,并且移除大部分的标点符号,然而还有其它不同行为的分词器存在。
例如,关键词,分词器完整地输出,接收到的同样的字符串,并不做任何分词。空格分词器只根据空格分割文本。正则分词器根据匹配正则表达式来分割文本。
词单元过滤器:
经过分词,作为结果的词单元流会按照指定的顺序通过指定的词单元过滤器。
词单元过滤器可以修改修改,添加或者移除词单元。我们已经提到过lowercase和stop词过滤器,但是在ElasticSearch里面还有很多可供选择的词单元过滤器。词干过滤器把单词遏制为词干。
ascii_folding过滤器移除变音符。
ngram和edge_ngram词单元过滤器可以产生适合与部分匹配或者自动补全的词单元。
(1)创建索引时自定义分词器
curl -X PUT http://elk103.k8s.com:9200/yinzhengjie
{
"settings":{
"analysis":{
"char_filter":{
"&_to_and":{
"type": "mapping",
"mappings": ["& => and"]
}
},
"filter":{
"my_stopwords":{
"type":"stop",
"stopwords":["the","a","if","are","to","be","kind"]
}
},
"analyzer":{
"my_analyzer":{
"type":"custom",
"char_filter":["html_strip","&_to_and"],
"tokenizer": "standard",
"filter":["lowercase","my_stopwords"]
}
}
}
}
}
analysis自定义分词器核心参数说明如下:
char_filter:
目的是将"&"转换为"and"字符。
filter:
过滤词汇,此处我使用stopwords来过滤掉一些停用词,即"the","a","if","are","to","be","kind"。
analyzer:
自定义分词器。
type:
指定分词器的类型,很明显,我指定的是自定义("custom")类型。
char_filter:
指定字符过滤器,可以指定多个,用逗号分隔。
tokenizer:
指定为标准的("standard")分词器。
filter:
指定过滤器。
(2)验证置自定义分词器是否生效
curl -X GET/POST http://elk103.k8s.com:9200/yinzhengjie/_analyze
{
"text":"If you are a person, please be kind to small animals.",
"analyzer":"my_analyzer"
}
九.索引模板(必讲)
1.索引模板的作用
索引模板是创建索引的一种方式。将数据写入指定索引时,如果该索引不存在,则根据索引名称能匹配相应索引模板话,会根据模板的配置建立索引。
推荐阅读:
https://www.elastic.co/guide/en/elasticsearch/reference/master/index-templates.html
2.查看内置的索引板
查看所有的索引模板信息:
curl -X GET http://elk101.k8s.com:9200/_template?pretty
查看某个索引模板信息:
curl -X GET http://elk101.k8s.com:9200/_template/k8s?pretty
3.创建索引模板
curl -X PUT http://elk101.k8s.com:9200/_template/k8s
{
"index_patterns": [
"k8s*"
],
"settings": {
"index": {
"number_of_shards": 5,
"number_of_replicas": 0,
"refresh_interval": "30s"
}
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"name": {
"type": "keyword"
},
"address": {
"type": "text"
}
}
}
}
4.删除索引模板
curl -X DELETE http://elk101.k8s.com:9200/_template/k8s
5.修改索引模板(注意修改是覆盖修改哟~)
curl -X PUT http://elk101.k8s.com:9200/_template/k8s
{
"index_patterns": [
"k8s*"
],
"settings": {
"index": {
"number_of_shards": 10,
"number_of_replicas": 0,
"refresh_interval": "30s"
}
},
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"gender": {
"type": "keyword"
}
}
}
}
6.创建索引进行测试
不指定副本和分片创建索引:
curl -X PUT http://elk101.k8s.com:9200/k8s
指定副本和分片创建索引:
curl -X PUT http://elk101.k8s.com:9200/k8s
{
"settings":{
"index":{
"number_of_replicas":1,
"number_of_shards":3
}
}
}
十.ES的Restful API使用过程中可能存在的问题
1.Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [brand] in order to load field data by uninverting the inverted index. Note that this can use significant memory.
故障原因:
基于brand字段进行分组查询,但很遗憾!
解决方案:
方案一:(不推荐,因为这可能会导致消耗更多的内存空间)
curl -X PUT http://elk101.k8s.com:9200/shopping/_mapping
{
"properties": {
"brand": { // 修改我们指定的字段,将"fielddata"修改为true。
"type": "text",
"fielddata": true
}
}
}
方案二:(推荐!)
curl -X POST/GET http://elk101.k8s.com:9200/shopping/_search
{
"aggs":{ // 聚合操作
"brand_group":{ // 该名称可以自定义,我习惯性基于相关字段起名称。
"terms":{ // 分组
"field":"brand.keyword" // 分组字段
}
}
}
}