作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
Analyzer & Analyze API
1、Analyzer的组成
分词器的作用是当一个文档被索引的时候,分词器从文档中提取出若干词元来支持索引的存储和搜索。
分析器(analyzer)都由三种构件组成的:character filters , tokenizers , token filters。
- Character filters(字符过滤器)
字符过滤器接收原始文本作为字符流,并可以通过添加、删除和更改字符来转换流。例如,可以使用字符过滤器将印度-阿拉伯数字(0123456789)转换成阿拉伯-拉丁语中的(0123456789),或从流中剥离<b>
等HTML元素。分析器可能有零个或多个字符过滤器,它们会按顺序应用。 - Tokenizer(分词器)
分词器接收到一串字符,将其分解为单独的词语(通常是单个单词),并输出词语流。例如,空白分词器每当看到任何空格时,将文本分解成词语。它将文本"Quick brown fox" 转换为词语[Quick,brown,fox!]。分词器还负责记录每个词语的顺序或位置以及体现词语的原始单词开始和结束字符偏移量。分析器必须只有一个分词器。 - Token filters(token过滤器)
词语过滤器接收词语流,并可以添加,删除和修改词语。例如,小写词语过滤器将所有词语转换为小写,停止词语过滤器会从词语流中删除常用字(停止字),同义词词语过滤器会将同义词引入到词语流中。词语过滤器不允许改变每个词语的位置或字符偏移量。分析器可以具有零个或多个词语过滤器,它们会按顺序应用。
三者顺序: Character Filters—>Tokenizer—>Token Filter
三者个数:Character Filters(0个或多个) + Tokenizer + Token Filters(0个或多个)
2、内置的Character Filters
2.1、HTML strip 字符过滤器
html_strip 字符过滤器去除像 <b>
这样的 HTML 元素,替换像&
为&
。
示例:
GET /_analyze
{
"tokenizer": "keyword",
"char_filter": [
"html_strip"
],
"text": "<p>I'm so <b>happy</b>!</p>"
}
返回:
{
"tokens" : [
{
"token" : "\nI'm so happy!\n",
"start_offset" : 0,
"end_offset" : 32,
"type" : "word",
"position" : 0
}
]
}
示例:创建索引时使用html_scrip
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "keyword",
"char_filter": [
"html_strip"
]
}
}
}
}
}
示例:自定义html_strip,跳过对<b>
的过滤
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "keyword",
"char_filter": [
"my_custom_html_strip_char_filter"
]
}
},
"char_filter": {
"my_custom_html_strip_char_filter": {
"type": "html_strip",
"escaped_tags": [
"b"
]
}
}
}
}
}
2.2、Mapping 字符过滤器
Mapping 字符过滤器用指定的替换替换任何出现的指定字符串。
映射字符过滤器接受键和值的映射。每当它遇到与键相同的字符串时,它都会用与该键相关联的值替换它们。
注意:匹配是贪婪的
示例:
GET /_analyze
{
"tokenizer": "keyword",
"char_filter": [
{
"type": "mapping",
"mappings": [
"٠ => 0",
"١ => 1",
"٢ => 2",
"٣ => 3",
"٤ => 4",
"٥ => 5",
"٦ => 6",
"٧ => 7",
"٨ => 8",
"٩ => 9"
]
}
],
"text": "My license plate is ٢٥٠١٥"
}
返回:
{
"tokens" : [
{
"token" : "My license plate is 25015",
"start_offset" : 0,
"end_offset" : 25,
"type" : "word",
"position" : 0
}
]
}
示例:自定义Mappp过滤器
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "standard",
"char_filter": [
"my_mappings_char_filter"
]
}
},
"char_filter": {
"my_mappings_char_filter": {
"type": "mapping",
"mappings": [
":) => _happy_",
":( => _sad_"
]
}
}
}
}
}
GET /my_index/_analyze
{
"tokenizer": "keyword",
"char_filter": [ "my_mappings_char_filter" ],
"text": "I'm delighted about it :("
}
返回:
{
"tokens" : [
{
"token" : "I'm delighted about it _sad_",
"start_offset" : 0,
"end_offset" : 25,
"type" : "word",
"position" : 0
}
]
}
示例:使用文本文件拓展映射
在实际的使用中,如果我们的 mapping 列表比较长,而且放在命令中不容易维护。我们可以在 Elasticsearch 的安装目录下的 config 子目录下创建一个叫做 analysis 的目录。
$ pwd
/Users/liuxg/elastic/elasticsearch-8.6.1/config
$ mkdir analysis
$ cd analysis
我们在这个目录下创建一个叫做 mappings.txt 的文件:
$ pwd
/Users/liuxg/elastic/elasticsearch-8.6.1/config
$ mkdir analysis
$ cd analysis
$ vi mappings.txt
$ cat analysis/mappings.txt
LOL => laughing out loud
BRB => be right back
OMG => oh my god
指定映射文件:
PUT index_with_mapping_char_filter_file
{
"settings": {
"analysis": {
"analyzer": {
"my_social_abbreviations_analyzer": {
"tokenizer": "keyword",
"char_filter": [
"my_social_abbreviations"
]
}
},
"char_filter": {
"my_social_abbreviations": {
"type": "mapping",
"mappings_path": "analysis/mappings.txt"
}
}
}
}
}
注意:mappings_path 是包含 key => value 映射的文件的路径。此路径必须是绝对路径或相对于 config 位置的路径,并且文件必须是 UTF-8 编码的。 文件中的每个映射必须用换行符分隔。必须指定 mappings_path 或 mappings 参数。
2.3、Patter replace 字符过滤器
pattern_replace 字符过滤器用指定的替换替换与正则表达式匹配的任何字符。
示例:
PUT my_index
{
"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/_analyze
{
"analyzer": "my_analyzer",
"text": "My credit card is 123-456-789"
}
返回:
{
"tokens" : [
{
"token" : "My",
"start_offset" : 0,
"end_offset" : 2,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "credit",
"start_offset" : 3,
"end_offset" : 9,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "card",
"start_offset" : 10,
"end_offset" : 14,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "is",
"start_offset" : 15,
"end_offset" : 17,
"type" : "<ALPHANUM>",
"position" : 3
},
{
"token" : "123",
"start_offset" : 18,
"end_offset" : 21,
"type" : "<NUM>",
"position" : 4
},
{
"token" : "456",
"start_offset" : 22,
"end_offset" : 25,
"type" : "<NUM>",
"position" : 5
},
{
"token" : "789",
"start_offset" : 26,
"end_offset" : 29,
"type" : "<NUM>",
"position" : 6
}
]
}
3、内置的Tokenizer
3.1、Standard Tokenizer(标准分词器)
standard(标准)分析器是默认分析器,如果没有指定分析器,则使用该分析器。
配置参数:
max_token_length
:最大词语长度。如果看到超过此长度的词语,则以max_token_length分割。默认为255。
示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "standard",
"max_token_length": 5
}
}
}
}
}
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
返回的词项:
[ The, 2, QUICK, Brown, Foxes, jumpe, d, over, the, lazy, dog's, bone ]
3.2、Simple Pattern Tokenizer(简单正则分词器)
使用正则表达式捕获匹配文本作为术语。它支持的正则表达式功能集必Pattern Tokenizer更有限,但标记化通常更快。
配置参数:
pattern
:用于匹配的正则表达式
示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "simple_pattern",
"pattern": "[0123456789]{3}"
}
}
}
}
}
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "fd-786-335-514-x"
}
返回的词项:
[ 786, 335, 514 ]
3.3、Simple Pattern Split Tokenizer(简单正则拆分分词器)
使用正则表达式在模式匹配时将输入拆分成词项。它支持的正则表达式功能集比模式标记器更有限,但标记化通常更快。
配置参数:
pattern
:用于匹配的正则表达式
示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "simple_pattern_split",
"pattern": "_"
}
}
}
}
}
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "an_underscored_phrase"
}
返回的词项:
[ an, underscored, phrase ]
3.4、Pattern Tokenizer(正则分词器)
当文本与单词分隔符匹配时,使用正则表达式将文本拆分为词项,或者将匹配的文本捕获为词项。
默认模式是\W+
,每当遇到非单词字符时都会拆分文本。
配置参数:
pattern
:用于匹配的正则表达式flags
:正则表达式标志。竖线分隔,例如CASE_INSENSITIVE|COMMENTS
group
:将哪个捕获组提取为词项。默认为-1(拆分)。
示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "pattern",
"pattern": ","
}
}
}
}
}
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "comma,separated,values"
}
返回的词项:
[ comma, separated, values ]
3.5、Whitespace Tokenizer(空格分词器)
每当文本遇到空格字符时,空格标记器都会将文本分解为词项。
示例:
POST _analyze
{
"tokenizer": "whitespace",
"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. ]
3.6、Char Group Tokenizer(字符组分词器)
只要文本遇到已定义集合中的字符,char_group分词器就会将文本分解为多个词项。在需要简单的定制标记化,并且使用Pattern tokenizer的开销是不可接受的情况下,它最有用。
配置参数:
tokenize_on_chars
:包含要将字符串标记化的字符列表的列表。每当遇到此列表中的字符时,都会开启一个新的词项。它接受单个字符,如-
、whitespace
、letter
、digit
、punctuation
、symbol
示例:
POST _analyze
{
"tokenizer": {
"type": "char_group",
"tokenize_on_chars": [
"whitespace",
"-",
"\n"
]
},
"text": "The QUICK brown-fox"
}
返回:
{
"tokens" : [
{
"token" : "The",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "QUICK",
"start_offset" : 4,
"end_offset" : 9,
"type" : "word",
"position" : 1
},
{
"token" : "brown",
"start_offset" : 10,
"end_offset" : 15,
"type" : "word",
"position" : 2
},
{
"token" : "fox",
"start_offset" : 16,
"end_offset" : 19,
"type" : "word",
"position" : 3
}
]
}
3.7、Classic Tokenizer(经典分词器)
经典分词器是一种基于语法的标记器,适用于英语文档。该标记器具有用于特殊处理首字母缩写、公司名称、电子邮件地址和互联网主机名的启发式。然而,这些规则并不总是有效的,对于除英语以外的大多数语言都不能很好地工作。
配置参数:
max_token_length
:最大词语长度。如果看到超过此长度的词语,则以max_token_length分割。默认为255。
示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "classic",
"max_token_length": 5
}
}
}
}
}
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
返回的词项:
[ The, 2, QUICK, Brown, Foxes, jumpe, d, over, the, lazy, dog's, bone ]
3.8、Edge n-gram tokenizer(边缘n元语法分词器)
无论何时遇到指定字符列表中的一个字符,edge_ngram分词器都会首先将文本分解为单词,然后发出每个单词的N-gram,其中N-gram的开头固定在单词的开头。
配置参数:
-
min_gram
:单个词源的最小字符长度,默认为1 -
max_gram
:单个词源的最大字符长度,默认为2 -
token_chars
:应包含在词项中的字符类。ElasticSearch将拆分不属于指定类的字符。默认为。字符类可以是以下任一类型:letter
:例如:a
,b
,ï
or京
digit
:例如:3
or7
whitespace
:例如:" "
or"\n"
punctuation
:例如:!
or''
symbol
:例如:$
or√
custom
:使用custom_token_chars
定制
-
custom_token_chars
:自定义字符。例如,将其设置为+-_
将使记号生成器将加号、减号和下划线符号视为记号的一部分。
示例:
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10,
"token_chars": [
"letter",
"digit"
]
}
}
}
}
}
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "2 Quick Foxes."
}
返回的词项:
[ Qu, Qui, Quic, Quick, Fo, Fox, Foxe, Foxes ]
3.9、Keyword Tokenizer(关键词分词器)
关键字分词器是一个“noop”标记器,它接受给定的任何文本,并输出与单个术语完全相同的文本。
示例:
POST _analyze
{
"tokenizer": "keyword",
"filter": [ "lowercase" ],
"text": "john.SMITH@example.COM"
}
返回:
{
"tokens" : [
{
"token" : "john.smith@example.com",
"start_offset" : 0,
"end_offset" : 22,
"type" : "word",
"position" : 0
}
]
}
3.10、Letter Tokenizer(字母分词器)
每当遇到非字母字符时,字母分词器都会将文本拆分成多个词项。多用于英语,不适用与汉语。
示例:
POST _analyze
{
"tokenizer": "letter",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
返回词项:
[ The, QUICK, Brown, Foxes, jumped, over, the, lazy, dog, s, bone ]
3.11、Lowercase Tokenizer(小写分词器)
小写分词器与字母分词器一样,在文本遇到非字母字符时将文本分解为词项,但它也会将所有词项小写。它在功能上等同于字母分词器和lowcase token filter的组合,但效率更高,因为它一次执行这两个步骤。
示例:
POST _analyze
{
"tokenizer": "lowercase",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog&#