# /
# 文本分析(Text analysis)
文本分析Text analysis是将非结构化文本(如电子邮件正文或产品描述)转换为针对搜索进行优化的结构化格式的过程。
在本节中
Configure text analysis //配置文本分析
Built-in analyzer //内置分析器
Tokenizer //分词器
Token filter //令牌过滤器
Character filters //字符过滤器
Normalizers //规范化器
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 分析器的组成(Composition of analyzer)
Anatomy of an analyzer 分析器的解剖
分析器 — 无论是内置的还是自定义的 — 只是一个包含三个较低级别构建块的包:
字符过滤器filters、
标记器tokenizers和
标记过滤器token filters。
1
2
3
4
5
2
3
4
5
# Character filters
字符过滤器用于在将字符流传递给标记器之前对其进行预处理。
字符过滤器接收作为字符流的原始文本,并可以通过添加、删除或更改字符来转换流。例如,字符过滤器可以用于转换印度-阿拉伯数字 (٠١٢٣٤٥٦٧٨٩) 转换为阿拉伯语-拉丁语等价物(0123456789),或者从流中剥离HTML元素(如<b>)。
Elasticsearch有许多内置的字符过滤器,可用于构建自定义分析器。
HTML Strip Character Filter:去除html元素,如< b >,并解码HTML实体,如& amp。
Mapping Character Filter:用指定的替换项替换任何出现的指定字符串。
Pattern Replace Character Filter:用指定的替换替换任何匹配正则表达式的字符。
1
2
3
4
5
6
7
2
3
4
5
6
7
# HTML Strip Character Filter
GET /_analyze
{
"tokenizer": "keyword",
"char_filter": [
"html_strip"
],
"text": "<p>I'm so <b>happy</b>!</p>"
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Mapping Character Filter
GET /_analyze
{
"tokenizer": "keyword",
"char_filter": [
{
"type": "mapping",
"mappings": [
"٠ => 0",
"١ => 1",
"٢ => 2",
"٣ => 3",
"٤ => 4",
"٥ => 5",
"٦ => 6",
"٧ => 7",
"٨ => 8",
"٩ => 9"
]
}
],
"text": "My license plate is ٢٥٠١٥"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Pattern Replace Character Filter
PUT my-index-00001
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "standard",
"char_filter": [
"my_char_filter"
]
}
},
"char_filter": {
"my_char_filter": {
"type": "pattern_replace",
"pattern": "(\\d+)-(?=\\d)",
"replacement": "$1_"
}
}
}
}
}
POST my-index-00001/_analyze
{
"analyzer": "my_analyzer",
"text": "My credit card is 123-456-789"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Tokenizer
断词器Tokenizer接收字符流,将其分解为单独的标记(通常是单独的单词),并输出标记流。例如,空白标记器在看到任何空白时都会将文本分解为标记。它会将文本“Quick brown fox!”转换为术语[Quick,brown,fox!]。
令牌化器还负责记录以下内容:
每个术语的顺序或位置(用于短语和单词接近度查询)
术语所代表的原始单词的开始和结束字符偏移量(用于突出显示搜索片段)。
令牌类型,生成的每个术语的分类,如、或。更简单的分析器只生成单词标记类型。
Elasticsearch有许多内置的标记器,可用于构建自定义分析器。
Standard Tokenizer:根据Unicode文本分割算法的定义,将文本划分为单词边界上的术语。它删除了大多数标点符号。它是大多数语言的最佳选择。
Letter Tokenizer:每当遇到非字母字符时,字母标记器就会将文本划分为多个术语。
Lowercase Tokenizer:小写标记器与字母标记器一样,每当遇到不是字母的字符时,都会将文本划分为多个术语,但它也会降低所有术语的大小写。
Whitespace Tokenizer:每当遇到任何空白字符时,空白标记器都会将文本划分为多个术语。
UAX URL Email Tokenizer:与标准令牌化器类似,只是它将url和电子邮件地址识别为单个令牌。
Classic Tokenizer:经典标记器是一种基于语法的英语标记器。
Thai Tokenizer:泰语标记器将泰语文本分割成单词。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Standard Tokenizer
POST _analyze
{
"tokenizer": "standard",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
上述句子将产生以下术语:
[ The, 2, QUICK, Brown, Foxes, jumped, over, the, lazy, dog's, bone ]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Token filter
令牌过滤器Token filter接受来自令牌化器的令牌流,并可以修改令牌(例如lowercasing)、删除令牌(例如stopwords)或添加令牌(例如synonyms)。
Elasticsearch有许多内置的令牌过滤器,可以用来构建自定义分析器。
1
2
2
# Lowercase Token Filter
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase",//Lowercase Token Filter
"asciifolding"//ASCII-Folding Token Filter
]
}
}
}
}
}
POST my-index-000001/_analyze
{
"analyzer": "my_custom_analyzer",
"text": "Is this <b>déjà vu</b>?"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Normalization token filters
规范化令牌筛选器
有几个可用的令牌过滤器,试图规范特定语言的特殊字符。
arabic_normalization 阿拉伯语
german_normalization 德国
hindi_normalization 印地语
indic_normalization 印度
sorani_normalization 库尔德语(索拉尼语)
persian_normalization 波斯语
scandinavian_normalization, scandinavian_folding 斯堪的纳维亚
serbian_normalization 塞尔维亚语
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 自定义分词器(Create a custom analyzer)
Elasticsearch有许多内置的令牌过滤器token filters,可以用来构建自定义分析器。
1
# my_custom_analyzer
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
}
}
POST my-index-000001/_analyze
{
"analyzer": "my_custom_analyzer",
"text": "Is this <b>déjà vu</b>?"
}
上面的例子产生了以下术语:
[ is, this, deja, vu ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 内置分析器(Built-in analyzer)
Built-in analyzer
Elasticsearch提供了广泛的内置分析器,无需进一步配置即可用于任何索引:
Standard Analyzer 标准分析器
Simple Analyzer 简单分析器
Whitespace Analyzer 空白分析器
Stop Analyzer 停止分析器
Keyword Analyzer 关键字分析器
Pattern Analyzer 模式分析器
Language Analyzers 语言分析器
Fingerprint Analyzer 指纹分析器
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 规范化器(Normalizers)
规范化器Normalizers 与分析器analyzers 类似,不同之处在于它们只能发出单个令牌。因此,它们没有标记化器,只接受可用的字符过滤器和标记过滤器的子集。只允许使用按字符工作的筛选器。例如,允许使用小写过滤器,但不允许使用词干过滤器,因为词干过滤器需要将关键字作为一个整体来查看。可以在规范化器中使用的过滤器的当前列表如下:
arabic_normalization,
asciifolding,
bengali_normalization,
cjk_width,
decimal_digit,
elision,
german_normalization,
hindi_normalization,
indic_normalization,
lowercase,
persian_normalization,
scandinavian_folding,
serbian_normalization,
sorani_normalization,
uppercase.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# IK中文分词器(IK Chinese Analyzer)
# 下载安装
#下载
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.0/elasticsearch-analysis-ik-7.10.0.zip
#安装
解压到/plugins/ik/
重启elasticsearch
1
2
3
4
5
6
2
3
4
5
6
# IK分词器介绍
主词库main.dic、停用词库stopword.dic、特殊词库、自定义词库。
https://github.com/medcl/elasticsearch-analysis-ik/
ik_max_word 和 ik_smart 什么区别?
ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;
ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。
1
2
3
4
5
2
3
4
5
GET easyes_document/_analyze
{
"analyzer": "ik_smart",
"text": ["测试内容1"]
}
1
2
3
4
5
2
3
4
5
{
"tokens" : [
{
"token" : "测试",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "内容",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "1",
"start_offset" : 4,
"end_offset" : 5,
"type" : "ARABIC",
"position" : 2
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 热更新分词库
# 基于远程文件词库(官方)
目前该插件支持热更新 IK 分词,通过上文在 IK 配置文件中提到的如下配置
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">location</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<entry key="remote_ext_stopwords">location</entry>
1
2
3
4
2
3
4
其中 location 是指一个 url,比如 http://yoursite.com/getCustomDict,该请求只需满足以下两点即可完成分词热更新。
1、该 http 请求需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
2、该 http 请求返回的内容格式是一行一个分词,换行符用 \n 即可。
满足上面两点要求就可以实现热更新分词了,不需要重启 ES 实例。
可以将需自动更新的热词放在一个 UTF-8 编码的 .txt 文件里,放在 nginx 或其他简易 http server 下,当 .txt 文件修改时,http server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag。可以另外做一个工具来从业务系统提取相关词汇,并更新这个 .txt 文件。
# 基于Mysql词库
1、在ik初始化词库源码处,会加载文件词库,新增加载Mysql词库。(这不是热更新)
2、热更新还要参考远程文件词库
热更新。