二、ElasticSearch倒排索引与分词
1、倒排索引概念:
1)百度百科:倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。
2)以书举例:
目录页 ===> 正排索引
索引页 ===> 倒排索引
3)正排索引和倒排索引:
A、正排索引:文档ID到文档内容、单词的关联关系
文档ID | 文档内容 |
1 | elasticsearch是最流行的搜索引擎 |
2 | php是世界上最好的语言 |
3 | 搜索引擎是如何产生的 |
B、倒排索引:单词到文档ID的关联关系
单词 | 文档ID列表 |
elasticsearch | 1 |
流行 | 1 |
搜索引擎 | 1,3 |
php | 2 |
世界 | 2 |
最好 | 2 |
语言 | 2 |
如何 | 3 |
诞生 | 3 |
C、查询包含“搜索引擎”的文档流程:
a、通过倒排索引,获得对应的文档ID:1,3;
b、通过文档ID,查询完整内容;
c、返回最终结果。
2、倒排索引详解:
1)组成:
A、单词词典(Term Dictionary)
B、倒排列表(Posting List)
2)单词词典:
记录所有文档的单词,一般都比较大,记录了单词到倒排列表的关联信息,一般使用B + Tree实现。构造方法见如下网址:
https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html。
3)倒排列表:
记录单词对应的文档集合,由倒排索引项Posting List组成。
A、倒排索引项主要包含:
a、文档ID。用于获取原始信息。
b、词频TF。记录该单词在该文档中的出现次数,用于计算相关性得分。
c、位置Position。记录单词在文档中的分词位置(多个),用于词语搜索。
d、偏移Offset。记录单词在文档的开始和结束位置,用于高亮显示。
B、如上的数据中,“搜索引擎”的Posting List为:
DocID | TF | Position | Offset |
1 | 1 | 2 | <18,22> |
3 | 1 | 0 | <0,4> |
3、分词介绍:
指:将文本转换成一系列单词Term/Token的过程,也可称作文本分析,ES中叫作:Analysis。
※分词器(Analyzer):
ES中专门处理分词的组件,组成和执行顺序如下:
A、Character Filters(多个)。针对原始文本进行处理,如:去除html特使标记符
等。B、Tokenizer(一个)。将原始文本按一定规则划分为单词。
C、Token Filters(多个)。针对Tokenizer处理的单词进行再加工,如:转小写、删除、新增等。
4、分词API:
ES提供了一个测试分词的API接口,使用endpoint:_analyze。
并且:可以指定分词器进行测试,还可以直接指定索引中的字段,甚至自定义分词器进行测试。
1)指定分词器:
#指定分词器进行分词测试
POST _analyze
{
"analyzer":"standard",
"text":"hello world!"
}
返回结果:
可以看到:a、分词结果;b、起始偏移;c、结束偏移;d、分词位置。
2)直接指定索引中字段:
#直接指定索引中字段
POST test_index/_analyze
{
"field":"username",
"text":"hello world!"
}
使用username字段的分词方式对text进行分词。
3)自定义分词器:
#自定义分词器,自定义Tokenizer、filter、等进行分词,举例:
POST _analyze
{
"tokenizer":"standard",
"filter":["lowercase"],
"text":"Hello World!"
}
返回结果:
可以看到:a、分词结果(已经变为小写);b、起始偏移;c、结束偏移;d、分词位置。
5、ES自带分词器:
1)standard(默认分词器) 按词划分、支持多语言、小写处理。
2)simple 按非字母划分、小写处理。
3)whitespace 按空格划分。
4)stop 按非字母划分、小写处理、按StopWord(语气助词:the、an、的、这等)处理。
5)keyword 不分词,作为一个单词输出。
6)pattern 通过正则表达式自定义分隔符,默认\w+,即:非字词的符号作为分隔符。
7)Language 另外还有30+常见语言的分词器(如:arabic、armenian、basque等)
6、中文分词器:
中文分词的难点在于:汉语中的分词没有一个形式上的分隔符,上下文不同,分词的结果也就不同,比如交叉歧义问题就会导致这样一个笑话:“南京市长江大桥欢迎你”,到底是“南京市长/江大桥/欢迎你”,还是“南京市/长江大桥/欢迎你”?
目前,常用的中文分词器有:
1)IK。实现中英文分词,支持多模式,可自定义词库,支持热更新分词词典。
2)jieba。python中流行,支持繁体分词、并行分词,可自定义词典、词性标记等。
7、自定义分词:
通过自定义:Character Filters、Tokenizer、Token Filter实现。格式:
PUT index名
{
"setting":{
"analysis":{
"char_filter":{},
"tokenizer":{},
"filter":{},
"analyzer":{}
}
}
}
举例:
#自定义分词
POST test_index
{
"settings":{
"analysis":{
"analyzer":{
"my_custom_analyzer":{
"type":"custom",
"tokenzier":"standartd",
"char_filter":"[
"html_strip"
],
"filter":[
"lowercase",
"asciifolding"
]
}
}
}
}
}