简介
做全文搜索就需要对文档分析、建索引。从文档中提取词元(Token)的算法称为分词器(Tokenizer),在分词前预处理的算法称为字符过滤器(Character Filter),进一步处理词元的算法称为词元过滤器(Token Filter),最后得到词(Term)。这整个分析算法称为分析器(Analyzer)。
分析器有3部分构成:
- character filters(字符过滤器):对原始文本进行加工操作,为后续的分词做准备;
- tokenizers(分词器):字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条;
- token filters(分词过滤器):接收分词器的处理结果,并可以将切分好的词语进行加工和修改,进而对分词结果进行规范化、统一化和优化处理。
Analyzer处理流程:
Analyzer按顺序做三件事:
- 使用CharacterFilter过滤字符;
- 使用Tokenizer分词;
- 使用TokenFilter过滤词。
DEMO
PUT /common_index
{
"settings": {
"analysis": {
"analyzer": {
"common_analyzer": { // 自定义分析器
"char_filter": ["html_strip"], // 字符过滤器
"tokenizer": "standard", // 分词器
"filter": ["lowercase"] // 分词过滤器
}
}
}
}
}
它完成以下工作:
- 使用
html_strip
字符过滤器,移除html标签; - 使用
standard
分词器分词; - 使用
lowercase
词过滤器,转为小写单词。
character filters(字符过滤器)
字符过滤器是分析器处理文本数据的第一道工序,它接收原始的字符流,对原始字符流中的字符进行添加、删除或者转换操作,进而改变原始的字符流。
ES内置的字符过滤器:
名称 | 功能 |
---|---|
映射关系字符过滤器 | 根据配置的映射关系替换字符 |
HTML擦除过滤器 | 去掉HTML元素 |
正则表达式替换过滤器 | 用正则表达式处理字符串 |
tokenizers(分词器)
分词器对文本进行切分后,需要保留词语与原始文本之间的对应关系,因此分词器还负责记录每个Token的位置,以及开始和结束的字符偏移量。
ES内置的分词器:
名称 | 功能 |
---|---|
标准分词器 | 对英文分词时,基于语法分词;对中文分词时,切分成单字 |
字母分词器 | 使用非字母的字符作为分词标记 |
小写分词器 | 功能上等同于字母分词器,并且把所有分词结果转换为小写形式 |
空格分词器 | 使用空格作为分词标记 |
token filters(分词过滤器)
ES内置的分词过滤器:
名称 | 功能 |
---|---|
Lower Case过滤器 | 将所有字母转换成小写形式 |
Stop Token过滤器 | 将停用词从分词结果中移除 |
同义词分词过滤器 | 为分词结果添加同义词 |
分析器的使用
测试分析API
通过analyze查看搜索关键词的分析结果:
POST /_analyze
{
"analyzer": "ik_smart",
"text": "测试结果"
}
运行结果:
{
"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
}
]
}
自定义分析器
手机号分词器:
PUT /mobile_index
{
"settings": {
"analysis": {
"char_filter": {
"digits_only": {
"type": "pattern_replace",
"pattern": "[^\\d]"
}
},
"tokenizer": {
"comm_number_tokenizer": {
"type": "ngram",
"token_chars": [
"digit"
],
"min_gram": "4",
"max_gram": "5"
}
},
"analyzer": {
"number_analyzer": {
"char_filter": "digits_only",
"tokenizer": "comm_number_tokenizer"
}
}
}
},
"mappings": {
"properties": {
"phone_number": {
"type": "text",
"analyzer": "number_analyzer"
}
}
}
}