Elasticsearch 篇之倒排索引与分词
书的目录与索引
正排索引
文档Id
|
文档内容
|
1
|
elasticsearch是最流行的搜索引擎
|
2
|
php是世界上最好的语言
|
3
|
搜索引擎是如何诞生的
|
倒排索引
单词
|
文档ID列表
|
elasticsearch
|
1
|
流行
|
2
|
搜索引擎
|
1,3
|
php
|
2
|
是
|
1,2,3
|
正排与倒排索引简介
查询包含"搜素引擎"的文档
-
通过倒排索引获得"搜索引擎"对应的文档Id有1和3
-
通过正排索引查询1和3的完整内容
-
返回用户最终结果
倒排索引详解
倒排索引组成
-
单词词典(Term Dictionary)是倒排索引的重要组成
-
记录所有文档的单词,一般都比较大
-
记录单词到倒排列表的关联信息
-
单词字典的实现一般是用B+ Tree,示例如下图:
-
倒排列表(Posting List)记录了单词对应的文档集合,由倒排索引项(Posting)组成
-
倒排索引项(Posting)主要包含如下信息:
-
文档Id,用于获取原始信息
-
单词频率(TF,Term Frequency):记录改单词在该文档中出现次数,用于后继相关性算分
-
位置(Position):记录单词在文档中的分词位置(多个),用于做词语搜索(Phrase Query)
-
偏移(Offser):记录单词在文档的开始和结束位置,用于做高亮显示
-
以"搜索引擎"为例
-
倒排索引与倒排列表整合在一起的结构如下:
-
es存储的是一个json格式的文档,其中包含多个字段,每个字段会有自己的倒排索引。
分词介绍
分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在es里面成为Analysis,如下图所示:
-
文本:elasticsearch是最流行的搜索引擎
-
分词结果:elasticsearch 流行 搜索引擎
分词器是es中专门处理分词的组件,英文为Analysis,它的组成如下:
-
Character Filters
-
Tokenizer
-
Token Filters
-
针对tokenizer处理的单词进行再加工,比如转小写,删除或新增等处理
analyze_api
es提供了一个测试分词的api接口,方便验证分词效果,endpoint是_analyze
-
可以直接指定analyze进行测试
POST _analyze
{
"analyzer": "standard",
"text": "hello word"
}
POST _analyze
{
"analyzer": "standard",
"filter": ["lowercase"],
"text": "Hello Word"
}
-
可以直接指定索引中的字段进行测试
-
可以自定义分词器进行测试
自带分词器
es自带如下的分词器
-
Standard
-
默认分词器
-
其组成如图,特性为:
-
按词切分,支持多语言
-
小写处理
-
Simple
-
其组成如图,特性为:
-
按照非字母切分
-
小写处理
POST _analyze
{
"analyzer": "simple",
"filter": ["lowercase"],
"text": "Hello Word 1"
}
-
Whitespace
-
其组成如图,特性为:
-
按照空格切分
POST _analyze
{
"analyzer": "whitespace",
"text": "Hello Word 1 啊"
}
-
Stop
-
Stop Word指语气助词等修饰性的词语,比如the、an、的、这等
-
其组成如图,特性为:
-
相比Simple多了Stop Word处理
POST _analyze
{
"analyzer": "stop",
"text": "Hello or and Word 1 啊"
}
-
Keyword
-
其组成如图,特性为:
-
不分词,直接将输入作为一个单词输出
POST _analyze
{
"analyzer": "keyword",
"text": "Hello or and Word 1 啊"
}
-
Pattern
-
其组成如图,特性为:
-
通过正则表达式自定义分隔符
-
默认是\W+,即非字词的符号作为分隔符
POST _analyze
{
"analyzer": "pattern",
"text": "Hello-Word day's"
}
中文分词
-
中文分词指的是将一个汉字序列切分成一个一个单独的词。在英文中,单词之间是以空格作为自然分界符,汉字中词没有一个形式上的分界符。
-
上下文不用,分词结果迥异,比如交叉歧义问题,比如下面两种分词都合理
-
常见分词系统
-
IK
-
实现中英文单词的切分,支持ik_smart、ik_maxword模式
-
可自定义词库,支持热更新分词词典
-
https://github.com/medcl/elasticsearch-analysis-ik
-
jieba
-
python中最流行的分词系统,支持分词和词性标注
-
支持繁体分词、自定义词典、并行分词等
-
https://github.com/sing1ee/elasticsearch-jieba-plugin
自定义分词
当自带的分词无法满足需求的时候,就需要自定义分词。
自定义分词就是通过Character Filters、Tokenizer和Token Filter实现。
自定义分词之CharacterFilter
在Tokenizer之前对原始文本进行处理,比如增加、删除或替换的字符等。
es自带的如下:
-
html_strip:去除html标签和转换html字体
-
Mapping:进行字符串替换
-
Pattern Replace:进行正则匹配替换
由于它是第一步,所以它的结果会影响Tokenizer和Token Filter解析的position和offset的结果
POST _analyze
{
"tokenizer": "keyword",
"char_filter": ["html_strip"],
"text": "<p>I'm so <b>happy</b>!</p>"
}
自定义分词之Tokenizer
自定义分词之 TokenFilter
分词使用说明
官方文档说明