tokenizer的输入是character filter 处理过的字符,是analyzer的第二步,他的功能是根据一定的规则或者词库进行分词,将text切成一个一个独立的token /term (词),输出是一个词的流token stream。举例来说 一个 whitespace
tokenizer 会用空格作为分词的边界。
同时,tokenizer 还需要记录每个term之间的顺序,该term在token流中以term为单位的offset,以及每个term在输入的character中的offset数据,就是当前term的开头对应了第几个character。每一个analyzer有且只能有一个tokenizer。
本文主要介绍elasticsearch自带的tokenizer,很多插件也提供了很多其他的tokenizers 。
1.Standard Tokenizer
标准分词器将文本划分为单词边界上的术语,这由Unicode文本分段算法定义。它删除大多数标点符号。这是大多数语言的最佳选择。
2.Letter Tokenizer
字母分词器在遇到非字母字符时会将文本分为多个术语。
3.Lowercase Tokenizer
小写分词器与字母分词器一样,在遇到非字母的字符时,会将文本分为多个词,但所有词都小写。
4.Whitespace Tokenizer
每当遇到任何空白字符时,空格tokenizer都会将文本划分为多个term。
5.UAX URL Email Tokenizer
uax_url_email tokenizer 类似于standard tokenizer,不同之处在于它将URL和电子邮件地址识别为单个token。
6.Classic Tokenizer
经典的分词器是用于英语的基本语法的分词器。
7.Thai Tokenizer
泰语分词器将泰语文本分成单词。
8.N-Gram Tokenizer
这个tokenizer比较特殊,对于查询不使用空格或长单词的语言(例如德语)很有用。
他会首先按照一定的规则进行分词,然后对每个词输出一个n-gram,就是类似把单词做了一个滑窗处理一样。
9.Edge N-Gram Tokenizer
作用类似n-gram,只是返回的分词结果是n-gram的一部分,他要求必须是从token的开头算起的n个char
10.Keyword Tokenizer
关键字分词器是一个“空”标记器,它接受给出的任何文本,并输出与输入完全相同的文本作为token。它可以与token filter (如lowercase)组合以对分析的术语进行归一化。
11.Pattern Tokenizer
模式分词器使用正则表达式在与单词分隔符匹配时将文本拆分为多个token,或将匹配的文本捕获为token。
12.Simple Pattern Tokenizer
simple_pattern 分词器使用正则表达式捕获匹配的文本作为term。它使用正则表达式功能的受限子集,并且通常比模式分词器更快。
13.Char Group Tokenizer
char_group分词器可通过分割字符集进行配置,通常比运行正则表达式轻量。
14.Simple Pattern Split Tokenizer
simple_pattern_split分词器使用与simple_pattern分词器相同的受限正则表达式子集,但是匹配的部分用来拆分输入,而不是将匹配部分作为结果返回。
15.Path Tokenizer
路径分词器path_hierarchy分词器采用类似于文件系统路径的分层值,在路径分隔符上拆分,并为树中的每个组件产生一个term,例如/foo/bar/baz -> [/foo,/foo/bar,/foo/bar/baz]。
标准分词器将文本划分为单词边界上的术语,这由Unicode文本分段算法定义。它删除大多数标点符号。这是大多数语言的最佳选择。unicode的语法定义看 这里
可配置的属性
max_token_length : 标识token的最大长度,超过这个长度的token将会按照长度切分。
样例
PUT /my_index?pretty
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "standard",
"max_token_length": 6
}
}
}
}
}
POST /my_index/_analyze?pretty
{
"analyzer": "my_analyzer",
"text": "2 QUICKLY Brown-Foxes \u0027s "
}
返回
{
"tokens" : [
{
"token" : "2",
"start_offset" : 0,
"end_offset" : 1,
"type" : "<NUM>",
"position" : 0
},
{
"token" : "QUICKL",
"start_offset" : 2,
"end_offset" : 8,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "Y",
"start_offset" : 8,
"end_offset" : 9,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "Brown",
"start_offset" : 10,
"end_offset" : 15,
"type" : "<ALPHANUM>",
"position" : 3
},
{
"token" : "Foxes",
"start_offset" : 16,
"end_offset" : 21,
"type" : "<ALPHANUM>",
"position" : 4
},
{
"token" : "s",
"start_offset" : 23,
"end_offset" : 24,
"type" : "<ALPHANUM>",
"position" : 5
}
]
}
可以看到QUICKLY 被切开了,同时 2的type和其他的不一样,2被识别成了数字。
这里的每个token元素还有几个属性
字母分词器在遇到非英文字母字符时会将文本分为多个术语。
没有可配置项
样例
POST _analyze
{
"tokenizer": "letter",
"text": "The 2 QUICK Brown-Foxes"
}
返回
{
"tokens" : [
{
"token" : "The",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "QUICK",
"start_offset" : 6,
"end_offset" : 11,
"type" : "word",
"position" : 1
},
{
"token" : "Brown",
"start_offset" : 12,
"end_offset" : 17,
"type" : "word",
"position" : 2
},
{
"token" : "Foxes",
"start_offset" : 18,
"end_offset" : 23,
"type" : "word",
"position" : 3
}
]
}
这个type又都变成了word了
小写分词器与字母分词器一样,在遇到非字母的字符时,会将文本分为多个词,但所有词都小写。
样例
POST _analyze
{
"tokenizer": "lowercase",
"text": "The 2 QUICK Brown-Foxes "
}
{
"tokens" : [
{
"token" : "the",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "quick",
"start_offset" : 6,
"end_offset" : 11,
"type" : "word",
"position" : 1
},
{
"token" : "brown",
"start_offset" : 12,
"end_offset" : 17,
"type" : "word",
"position" : 2
},
{
"token" : "foxes",
"start_offset" : 18,
"end_offset" : 23,
"type" : "word",
"position" : 3
}
]
}
可以看到和letter-tokenizer是一样的。只是附加转换成了小写的形式。
每当遇到任何空白字符时,空白令牌生成器都会将文本划分为多个术语。
可以有这个配置
max_token_length 同Standard Tokenizer
样例
POST _analyze
{
"tokenizer": "whitespace",
"text": "The 2 QUICK Brown-Foxes "
}
返回
{
"tokens" : [
{
"token" : "The",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "2",
"start_offset" : 4,
"end_offset" : 5,
"type" : "word",
"position" : 1
},
{
"token" : "QUICK",
"start_offset" : 6,
"end_offset" : 11,
"type" : "word",
"position" : 2
},
{
"token" : "Brown-Foxes",
"start_offset" : 12,
"end_offset" : 23,
"type" : "word",
"position" : 3
}
]
}
返回为[The, 2, QUICK, Brown-Foxes]
uax_url_email tokenizer 类似于standard tokenizer,不同之处在于它将URL和电子邮件地址识别为单个token。
可以有这个配置
max_token_length 同Standard Tokenizer
样例
POST _analyze
{
"tokenizer": "uax_url_email",
"text": "Email me at john.smith@global-international.com"
}
返回
{
"tokens" : [
{
"token" : "Email",
"start_offset" : 0,
"end_offset" : 5,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "me",
"start_offset" : 6,
"end_offset" : 8,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "at",
"start_offset" : 9,
"end_offset" : 11,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "john.smith@global-international.com",
"start_offset" : 12,
"end_offset" : 47,
"type" : "<EMAIL>",
"position" : 3
}
]
}
经典的分词器是用于英语的基于语法的分词器。对于纯英文的文档分词效果比较好。
可以有这个配置
max_token_length 同Standard Tokenizer
样例
POST _analyze
{
"tokenizer": "classic",
"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
返回
{
"tokens" : [
{
"token" : "The",
"type" : "<ALPHANUM>",
},
{
"token" : "2",
"type" : "<ALPHANUM>",
},
{
"token" : "QUICK",
"type" : "<ALPHANUM>",
},
{
"token" : "Brown",
"type" : "<ALPHANUM>",
},
{
"token" : "Foxes",
"type" : "<ALPHANUM>",
},
{
"token" : "jumped",
"type" : "<ALPHANUM>",
},
{
"token" : "over",
"type" : "<ALPHANUM>",
},
{
"token" : "the",
"type" : "<ALPHANUM>",
},
{
"token" : "lazy",
"type" : "<ALPHANUM>",
},
{
"token" : "dog's",
"type" : "<APOSTROPHE>",
},
{
"token" : "bone",
"type" : "<ALPHANUM>",
}
]
}
为了看着更方便,删掉了start_offset,end_offset,position三个属性,这里可以看到不同的tokenizer识别出来的type还有有很大的区别的
泰语分词器将泰语文本分成单词。
估计对我们这个使用很少
样例
POST _analyze
{
"tokenizer": "thai",
"text": "การที่ได้ต้องแสดงว่างานดี"
}
这个tokenizer比较特殊,对于查询不使用空格或长单词的语言(例如德语)很有用。
他会首先按照一定的规则进行分词,然后对每个词输出一个n-gram,就是类似把单词做了一个滑窗处理一样。
样例
POST _analyze
{
"tokenizer": "ngram",
"text": "Quick Fox"
}
得到的结果
[ Q, Qu, u, ui, i, ic, c, ck, k, "k ", " ", " F", F, Fo, o, ox, x ]
有三个属性可以设置
min_gram:默认为1 滑窗内字符串最短数量
max_gram:默认为2 滑窗内字符串最长数量
token_chars:term包含的字符,那些不属于这里的字符用来分词产生term,默认token_chars是所有的字符,整个输入作为一个term
复杂一些的样例
PUT analyze_test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "n_tokenizer"
}
},
"tokenizer": {
"n_tokenizer": {
"type": "ngram",
"min_gram": 5,
"max_gram": 5,
"token_chars": [
"letter",
"digit"
]
}
}
}
}
}
POST analyze_test/_analyze
{
"analyzer": "my_analyzer",
"text": ["i like beautiful scenery"]
}
返回的token
["beaut"," eauti"," autif"," utifu"," tiful"," scene"," cener"," enery"]
因为字符2的长度小于3,所以不会被输出,假如是下面的
POST my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "212 Quick Foxes."
}
返回
[ 212, Qui, uic, ick, Fox, oxe, xes ]
作用类似n-gram,只是返回的分词结果是n-gram的一部分,他要求必须是从token的开头算起的n个char
有三个属性可以设置
min_gram:默认为1
min_gram:默认为2
token_chars:term包含的字符,哪些不属于这里的字符用来分词产生term,默认token_chars是所有的字符,整个输入作为一个term
样例
PUT analyze_test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "edge_tokenizer"
}
},
"tokenizer": {
"edge_tokenizer": {
"type": "edge_ngram",
"min_gram": 5,
"max_gram": 5,
"token_chars": [
"letter",
"digit"
]
}
}
}
}
}
POST analyze_test/_analyze
{
"analyzer": "my_analyzer",
"text": ["i like beautiful scenery"]
}
返回
{
"tokens" : [
{
"token" : "beaut",
"start_offset" : 7,
"end_offset" : 12,
"type" : "word",
"position" : 0
},
{
"token" : "scene",
"start_offset" : 17,
"end_offset" : 22,
"type" : "word",
"position" : 1
}
]
}
可以看到这里的每一个term都是取前缀的操作,而且长度小于5的直接就会被忽略掉了
关键字分词器是一个“空”标记器,它接受给出的任何文本,并输出与输入完全相同的文本作为token。它可以与token filter (如lowercase)组合以对分析的术语进行归一化。
样例
POST _analyze
{
"tokenizer": "keyword",
"text": "New York"
}
返回
[ New York ]
注意,这里没有逗号 ,
所以是一个词,这个词包含空格
模式分词器使用正则表达式在与单词分隔符匹配时将文本拆分为多个token,或将匹配的文本捕获为token。
有三个属性
pattern:正则表达式
flag: java flags,“CASE_INSENSITIVE|COMMENTS”
group: 是获取group作为token还是把匹配的字符串作为split,默认为-1,split
样例
curl -X PUT "localhost:9200/my_index?pretty" -H 'Content-Type: application/json' -d'
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "pattern",
"pattern": ","
}
}
}
}
}
'
curl -X POST "localhost:9200/my_index/_analyze?pretty" -H 'Content-Type: application/json' -d'
{
"analyzer": "my_analyzer",
"text": "comma,separated,values"
}
'
返回
[ comma, separated, values ]
simple_pattern 分词器使用正则表达式捕获匹配的文本作为term。它使用正则表达式功能的受限子集,并且通常比模式分词器更快。
只有一个属性
pattern
样例
{
"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-786335-514-x"
}
返回
[ 786, 335, 514 ]
char_group分词器可通过分割字符集进行配置,通常比运行正则表达式轻量。
属性
tokenize_on_chars:
POST _analyze
{
"tokenizer": {
"type": "char_group",
"tokenize_on_chars": [
"whitespace",
"-",
"\n"
]
},
"text": "The QUICK brown-fox"
}
返回
[The, QUICK , brown, fox]
simple_pattern_split分词器使用与simple_pattern分词器相同的受限正则表达式子集,但是匹配的部分用来拆分输入,而不是将匹配部分作为结果返回。
属性
pattern:用来做split的正则
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]
路径分词器path_hierarchy分词器采用类似于文件系统路径的分层值,在路径分隔符上拆分,并为树中的每个组件产生一个term,例如/foo/bar/baz -> [/foo,/foo/bar,/foo/bar/b
POST _analyze
{
"tokenizer": "path_hierarchy",
"text": "/one/two/three"
}
返回
[ /one, /one/two, /one/two/three ]