Elasticsearch(es)自定义分词器,根据特殊符号分词或分词后保留特殊符号
1.需求:
现在有个原始文本:"电阻@CAL-CHIP@55@55w@±1%@330Ω@1/8W@55℃@xiaolong(电脑)@3000HF",如果使用官方分词器,分词之后的结果如下:
{
"tokens": [
{
"token": "电",
"start_offset": 0,
"end_offset": 1,
"type": "<IDEOGRAPHIC>",
"position": 0
},
{
"token": "阻",
"start_offset": 1,
"end_offset": 2,
"type": "<IDEOGRAPHIC>",
"position": 1
},
{
"token": "cal",
"start_offset": 3,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "chip",
"start_offset": 7,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "55",
"start_offset": 12,
"end_offset": 14,
"type": "<NUM>",
"position": 4
},
{
"token": "55w",
"start_offset": 15,
"end_offset": 18,
"type": "<ALPHANUM>",
"position": 5
},
{
"token": "1",
"start_offset": 20,
"end_offset": 21,
"type": "<NUM>",
"position": 6
},
{
"token": "330ω",
"start_offset": 23,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 7
},
{
"token": "1",
"start_offset": 28,
"end_offset": 29,
"type": "<NUM>",
"position": 8
},
{
"token": "8w",
"start_offset": 30,
"end_offset": 32,
"type": "<ALPHANUM>",
"position": 9
},
{
"token": "55",
"start_offset": 33,
"end_offset": 35,
"type": "<NUM>",
"position": 10
},
{
"token": "xiaolong",
"start_offset": 37,
"end_offset": 45,
"type": "<ALPHANUM>",
"position": 11
},
{
"token": "电",
"start_offset": 46,
"end_offset": 47,
"type": "<IDEOGRAPHIC>",
"position": 12
},
{
"token": "脑",
"start_offset": 47,
"end_offset": 48,
"type": "<IDEOGRAPHIC>",
"position": 13
},
{
"token": "3000hf",
"start_offset": 50,
"end_offset": 56,
"type": "<ALPHANUM>",
"position": 14
}
]
}
可以看到,这个分词之后的结果是以:@,-,±,%,/,℃ 这些符号为界限把词给分开,并且遇到中文的时候,分词的结果是要逐字分词,现在我需要实现的效果是:原来分词的效果不变,只是不能把 ℃ 这个符号给去掉,也就是说理想的结果是这样的:
........
{
"token": "8w",
"start_offset": 30,
"end_offset": 32,
"type": "<ALPHANUM>",
"position": 9
},
{
"token": "55℃",
"start_offset": 33,
"end_offset": 35,
"type": "<NUM>",
"position": 10
},
{
"token": "xiaolong",
"start_offset": 37,
"end_offset": 45,
"type": "<ALPHANUM>",
"position": 11
},
.....
2.通过自定义分词器来实现:
{
"settings": {
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "combined_tokenizer",
"char_filter": ["chinese_space_char_filter"]
}
},
"tokenizer": {
"combined_tokenizer": {
"type": "pattern",
"pattern": [
"-|@|,|!|?|=|/|±| |(|)|?"
]
}
},
"char_filter": {
"chinese_space_char_filter": {
"type": "pattern_replace",
"pattern": "([\\u4e00-\\u9fa5])",
"replacement": " $1 "
}
}
}
},
"mappings": {
"properties": {
"parameterSplicing": {
"type": "text",
"analyzer": "custom_analyzer",
"index": true,
"store": false
}
}
}
}
通过这个来作为分词器,然后分词效果如下:
{
"analyzer": "custom_analyzer",
"text": "电阻@CAL-CHIP@55@55w@±1%@330Ω@1/8W@55℃@xiaolong(小龙牌电脑)@3000HF"
}
分词结果:
{
"tokens": [
{
"token": "电",
"start_offset": 0,
"end_offset": 0,
"type": "word",
"position": 0
},
{
"token": "阻",
"start_offset": 1,
"end_offset": 1,
"type": "word",
"position": 1
},
{
"token": "CAL",
"start_offset": 3,
"end_offset": 6,
"type": "word",
"position": 2
},
{
"token": "CHIP",
"start_offset": 7,
"end_offset": 11,
"type": "word",
"position": 3
},
{
"token": "55",
"start_offset": 12,
"end_offset": 14,
"type": "word",
"position": 4
},
{
"token": "55w",
"start_offset": 15,
"end_offset": 18,
"type": "word",
"position": 5
},
{
"token": "1%",
"start_offset": 20,
"end_offset": 22,
"type": "word",
"position": 6
},
{
"token": "330Ω",
"start_offset": 23,
"end_offset": 27,
"type": "word",
"position": 7
},
{
"token": "1",
"start_offset": 28,
"end_offset": 29,
"type": "word",
"position": 8
},
{
"token": "8W",
"start_offset": 30,
"end_offset": 32,
"type": "word",
"position": 9
},
{
"token": "55℃",
"start_offset": 33,
"end_offset": 36,
"type": "word",
"position": 10
},
{
"token": "xiaolong",
"start_offset": 37,
"end_offset": 45,
"type": "word",
"position": 11
},
{
"token": "小",
"start_offset": 46,
"end_offset": 46,
"type": "word",
"position": 12
},
{
"token": "龙",
"start_offset": 47,
"end_offset": 47,
"type": "word",
"position": 13
},
{
"token": "牌",
"start_offset": 48,
"end_offset": 48,
"type": "word",
"position": 14
},
{
"token": "电",
"start_offset": 49,
"end_offset": 49,
"type": "word",
"position": 15
},
{
"token": "脑",
"start_offset": 50,
"end_offset": 50,
"type": "word",
"position": 16
},
{
"token": "3000HF",
"start_offset": 53,
"end_offset": 59,
"type": "word",
"position": 17
}
]
}
可以看到,这个 55℃ 被完整的保留下来了,
3.解释:
1.
settings
部分
analysis
节点:这是整个分析器相关配置的核心节点,用于定义各种分析组件,像分析器(analyzer
)、分词器(tokenizer
)以及字符过滤器(char_filter
)等。
analyzer
节点(自定义分析器定义):
custom_analyzer
:这是自定义的一个分析器名称,它的类型被指定为custom
,意味着需要自行组合各种组件(分词器、字符过滤器等)来构建其功能。- 组件配置:它使用了名为
combined_tokenizer
的分词器,并且关联了一个名为chinese_space_char_filter
的字符过滤器。通过这样的搭配,文本在经过这个分析器处理时,会先由combined_tokenizer
进行初步的分词操作,然后再经过chinese_space_char_filter
做进一步的文本处理(后文会详细介绍具体处理内容)。tokenizer
节点(分词器定义):
combined_tokenizer
:具体定义了一个名为combined_tokenizer
的分词器,其类型是pattern
,也就是基于正则表达式模式来进行分词操作。pattern
配置:其pattern
属性值为-|@|,|!|?|=|/|±| |(|)|?
,这是一个正则表达式模式,含义是以 “或” 的关系罗列了一系列用于分词的标识符号。具体来说,文本中一旦出现-
、@
、,
、!
、?
、=
、/
、±
、空格、(
、)
这些符号中的任意一个,分词器就会在该符号出现的位置将文本分割成不同的词项。例如,对于文本"电阻@CAL-CHIP@0805@±1%@330Ω@1/8W@55℃"
,就会依据这些符号进行相应的拆分,像根据@
把各个不同部分拆分开等。char_filter
节点(字符过滤器定义):
chinese_space_char_filter
:定义了一个字符过滤器,类型为pattern_replace
,主要用于对文本中的中文字符进行特定处理。pattern
和replacement
配置:pattern
属性值为([\\u4e00-\\u9fa5])
,这是利用 Unicode 编码范围来匹配任意单个中文字符,并且使用括号进行了分组捕获;replacement
属性值为$1
,表示将匹配到的单个中文字符(也就是前面分组捕获的内容)前后都添加一个空格。这样做的目的是在分词之后,对于文本里出现的中文部分,每个中文字符都能以添加前后空格的形式存在,方便后续可能的进一步文本处理或者索引、查询匹配等操作,使其在文本结构上更清晰、便于区分。
在这里需要重点说明一下,之所以遇到中文可以逐字分词,那是因为通过字符过滤器,在分词之前把中文的每一个字前后都加上了空格,然后在分词器里面有定义:遇到空格就进行分词,所以就可以做到分词之后的效果是逐字分词