索引分词原理
倒排索引
每个全文索引都是一个倒排索引,ES 在进行检索操作时,会建立倒排索引,将拆分的词进行处理,提高索引命中率。
以下索引已有2个 segment,从 data resource 接收到了新的数据会先存入 buffer,buffer 将数据刷到文件系统缓存中, 生成一个新的 segment,此时已经可以进行检索这个 segment,之后再被刷入磁盘中。
倒排索引流程
分词器(analyzer)
不管是内置还是自定义的分词器,都可以视为一种包含了三种基础架构的包,分别是字符过滤器(Character filters)、标记器(Tokenizer)和 令牌过滤器(Token filters)。
字符过滤器(Character filters)
在将字符传递给标记器之前进行预处理,在接收原始文本后进行一系列的增、删、改操作来转换字符流。
HTML Strip Char Filter
可从文本中剥离 HTML 元素,并用它们的解码值替换 HTML 实体(例如用 & 替换 &)
代码语言:javascript复制POST _analyze
{
"tokenizer": "keyword",
"char_filter": [ "html_strip" ],
"text": "<p>Tencent Cloud & <b>ES</b>!</p>"
}
Mapping Chartacter Filter
可映射键值对,遇到相同的键时可替换成关联词;贪婪模式匹配,替换的字符串允许空字符串。
Pattern Replace Char Filter
用正则表达式来匹配应该用指定的替换字符串替换的字符。 替换字符串可以引用正则表达式中的捕获组。
如以下实例,执行后,原本的“123-456-789”会返回“123_456_789”
代码语言:javascript复制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"
}
Tokenizer(标记器)
标记器在接收到字符流后会分解为独立的标记,并输出一个标记流。常见的标记器如下
tokenizer | description |
---|---|
standard tokenizer | 标准标记器,删除大多数标点符号,适用于绝大多数语言 |
letter tokenizer | 遇到非字母的字符时,标记器会将文本标为 terms |
lowercase tokenizer | 类似 letter tokenizer,遇到非字母 |
whitespace tokenizer | 遇到空白字符时,会将文本标记为 terms |
UAX URL email tokenizer | 类似于 classic tokenizer,将 URL 和 email 地址识别为令牌 |
classic tokenizer | 基于语法的标准标记器 |
Thai tokenizer | 针对泰语的标记器 |
Token filters(令牌过滤器)
接收标记器,可对标记器进行增、删、改操作
内置分词器
analyzer | description |
---|---|
standard analyzer | 默认分析器,如果未指定,则使用该分析器。它提供基于语法的标记化,适用于绝大多数语言 |
simple analyzer | 当 simple 分词器遇到非字母的字符时,会将文本划分为多个术语。小写所有术语 |
whitespace Analyzer | 遇到空白字符时,会将空白字符分解为 terms,非小写 terms |
stop analyzer | 类似 simple 分词器,支持去除停止词 |
keyword analyzer | 不分词,内容整体作为一个 token(not_analyzed) |
pattern analyzer | 正则表达式分词,默认匹配W |
language analyzers | 多种语言分词器 |
Fingerprint Analyzer | 专业的指纹分词器,可创建指纹重复使用 |
Keyword 对比 text
keyword | text |
---|---|
不会分词建立索引 | 会分词建立索引 |
支持模糊、精确查询 | 支持模糊、精确查询 |
支持聚合 | 不支持聚合 |
IK 分词的运用
IK 分词的两种模式
ik_smart:以最粗粒度进行分词
ik_max_word:以最细粒度进行分词,穷尽各种可能的组合
IK 分词实践
创建索引的时候用 ik_max_word,搜索数据时用 ik_smart,以保证数据在存入索引时最细粒度拆分,搜索数据时更精确的获取到想要的结果。
创建索引
代码语言:javascript复制PUT shani_ik
{
"settings": {
"index.analysis.analyzer.default.type": "ik_max_word"
},
"mappings": {
"doc" : {
"properties": {
"dep_test": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
检索数据
代码语言:javascript复制GET shani_ik
{
"text": "我爱北京天安门",
"analyzer": "ik_smart"
}
ES 分词进阶运用
自定义分词器
内建分词无法满足需求时,可自定义分词器
关闭索引
在修改自定义之前,需要关闭索引
向索引中添加自定义分词器
代码语言:javascript复制PUT shani/settings
{
"analysis": {
"char_filter": {
"&_to_and": {
"type": "mapping",
"mappings": ["& => and"]
}
},
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": ["the", "a"]
}
},
"analyzer": {
"shani_analyzer": {
"type": "custom",
"char_filter": ["html_strip", "@_to_and"],
"tokenizer": "ik_max_word",
"filter": ["lowercase", "my_stopwords"]
}
}
}
}