这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
Index: 索引
索引包含一堆具有相似结构的文档数据,比如可以有客户索引、商品分类索引等。
一个Index包含多个document,一个Index代表一类类似或者相同的document
Type(类型表):type是index种的一个逻辑数据分类。document相当于一行记录,通常用json来表示。
mappging: 映射-约束,数据如何存放到索引对象,需要有一个映射配置,包括:数据类型、是否存储、是否分词。mapping用来定义document中每个字段的类型,即所使用的analyzer、是否索引等属性,非常关键等。
| 关系型数据库mysql | 非关系型数据库 |
|---|---|
| 数据库Database | 索引Index |
| 表Table | 类型Type |
| 数据行Row | 文档Document |
| 数据列Column | 字段Field |
| 约束Schema | 映射Mapping |
倒排索引
指的是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并返回给用户。全文检索使用的是倒排索引。
倒排索引的流程:
数据库中的数据->对数据进行切词->进行倒排索引排序
数据库中的数据,例如100w条数据,按照数据库存储,就需要扫描100w次,而且每次扫描都需要匹配文本所有的字符,确认是否包含搜索的关键词,而且不能将搜索的次进行拆分。
利用倒排索引,假设100w条数据,拆分词语 1000w条,那么在倒排索引中就会有1000w条数据,可能搜索前面几个,也可能搜索全部。相对比来说,索引搜索还是比较快的。
正排索引
正排索引相对倒排就简单多了,实际上就是一个字典文件,key是DocId,value是这个DocId对应的内容,主要用来做结果集的过滤,所谓倒排检索,正排过滤,什么场景需要这样的东西呢?下面的场景你肯定经历过。
你在一个某东的网站搜索运动鞋,肯定出来一堆鞋子,但是你只想看nike的鞋子,这时候你可以再运动鞋后面加上Nike,搜索nike运动鞋,但是结果不一定准,因为并不是每个nike的鞋子的标题上都会写上nike,这时候就需要用到正排了,他会把nike鞋子给你过滤出来。
正排索引就是一个数组,数组的下标就是DocId。
正排索引和倒排索引的区别
正排索引:由文档指向关键词
文档docId->单词1,单词2
单词1 出现的次数 单词出现的位置; 单词2 出现的次数 出现的位置
倒排索引:由关键词指向文档
单词1->文档docId_1, 文档docId_2, 文档docId_3...
单词2->文档docId_1, 文档docId_2
正派索引是不能直接用于排名的,如果只存在正排索引,排名程序需要扫描所有索引库中的文件,找到包含这个关键词的文件,再进行相关性的计算,这样就不能实时返回排名结果。
所以搜索引擎会将正排索引数据库重新构造为倒排索引,把页面对应到关键词的关系表,转化为关键词对应的页面。
因此当用户搜索关键词的时候,排名程序在倒排索引中定位这个关键词,就可以马上找到所有包含这个关键词的页面。
存储数据和搜索数据流程
倒排索引是搜索引擎基础中的基础,主要的检索都是从倒排索引开始的,所以,首先设计一个倒排索引的数据结构是所有搜索引擎的基础。
搜索引擎的基础是DocId,也就是文档ID,DocId是唯一的并且是连续的,而倒排索引就是一组DocId链表,每个链表对应一个关键词。
假设有这么五个文档需要进行搜索:
| 文档编号 | 内容 |
|---|---|
| 1 | 你好,搜索引擎 |
| 2 | 搜索引擎有一条数据 |
| 3 | 你好,有一条测试数据 |
那么建立出来的倒排索引的基础结构如下图:
| 关键词 | 文档编号 |
|---|---|
| 你好 | 1,3 |
| 搜索引擎 | 1,2 |
| 数据 | 2,3 |
| 有一条 | 2,3 |
| 测试 | 3 |
所以,当我们**检索数据**这个词的时候,就能迅速的定位到2,3这两个文档中有这个数据。
关键就在于检索数据这个过程,如何能迅速的定位到第三行数据,从而知道数据这个词在文档2,3中。这里就用到哈希表了。
一个完整的倒排包括两部分,一个是上面那个表,还有一个就是哈希表,通过哈希表就能知道数据这个词的下标为3,从而找到2,3这两个文档。
总之,对于一个关键词的定位:
- 首先,通过计算这个关键词的hash,得到它的倒排索引的下标。
- 然后,查找倒排索引的下标,得到文档ID的链表
一次简单的检索过程:
- 输入关键词
搜索引擎 - 在表2中查找到这个关键词在第2行,(使用哈希表)
- 找到第2行中的第2列,把文档编号docId找出来,是1和2
- 去表1中通过文档编号,把每个文档的实际内容找出来
- 将1和2的结果显示出来
- 搜索完成