注:本模块会大量用到protobuf库、cppjieba库,不了解的读者可以先去简单了解一下这两个库怎么使用,这里就不赘述了。
(为了避免本模块的内容过长,笔者分两篇完成,第一篇讲搜索引擎索引的基础知识和这个项目中索引模块的基础架构,第二篇讲索引模块的具体技术实现细节。)
一、对Boost官网网页的预处理
注:这个过程用什么语言处理都可以
附:code
由于Boost官网的数据都是以网页的形式呈现的,但是制作索引的时候直接对网页进行操作就比较麻烦,所以这个阶段就是对Boost官网的网页数据先做一个预处理,将它变成制作索引的时候容易处理的形式。
这里采用将每一个网页处理成一行数据,然后每个网页的标题、url以及正文用一个分隔符隔开的形式:url\3title\3content
。这个分隔符之所以选择一个不可见字符(\3
)是因为,如果分隔符选择可见字符,可能会和文档中包含的内容冲突。
二、有关索引结构的设计
在实现之前,先介绍一下“索引”的概念。
2.1 单词-文档矩阵
单词文档矩阵时表达两者之间所具有的一种包含关系的概念模型。通常逻辑上就像这样:
文档1 | 文档2 | 文档3 | 文档4 | |
---|---|---|---|---|
词汇1 | √ | √ | ||
词汇2 | √ | √ | ||
词汇3 | √ | √ | ||
词汇4 | √ |
从纵向即文档这个维度来看,每列表示文档包含了哪些单词,比如:文档1包含词汇1和词汇3,而不包含其他单词。从横向即词汇这个维度来看,每行代表了哪些文档包含这个单词。比如对于词汇1来说,文档1和文档3包含这个词汇,而其他文档不包含这个词汇。矩阵的其他行列同上解读。
搜索引擎的索引其实就是实现单词-文档矩阵的具体数据结构。这个可以有不同的方式来实现上述概念模型,倒排索引是经过实验数据验证表示单词到文档的映射关系的最佳实现方式。除了倒排索引外,还可以用签名文件、后缀树等方式实现,这里主要讲用倒排索引实现的技术细节(TODO:这里后面会有一个链接~)。
2.2 倒排索引相关的基本概念
- 文档:这里的文档就是Boost网站的HTML格式的网页;
- 文档编号:为了方便内部处理,为文档集合内每一个文档赋予一个唯一的内部编号,以此编号作为这个文档的唯一标识。
- 倒排列表:倒排列表记载了出现过某个单词的所有文档的文档列表。
2.3 倒排索引的基本概念
倒排索引是实现单词-文档矩阵映射关系的一种具体存储形式,通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。
通过概念可以看出倒排索引由两部分构成:单词和倒排列表。
下面通过一个例子来详细说明倒排索引的结构:
假设有一个文档集合包含5个文档:
文档编号 | 文档内容 |
---|---|
1 | 谷歌地图之父跳槽Facebook |
2 | 谷歌地图之父加盟Facebook |
3 | 谷歌地图创始人拉斯离开谷歌加盟Facebook |
4 | 谷歌地图之父跳槽Facebook与Wave项目取消有关 |
5 | 谷歌地图之父拉斯加盟社交网站Facebook |
由于文档内容都是由很多单词构成的,而我们在建立倒排索引的时候首先要将其切分为很多单词,这里就涉及到分词技术,这里不详述,后面会介绍。经过一系列构建过程后,建成的倒排索引结构就是下面这样子的:
下面这个是最简单的倒排索引结构,但是足以说明问题。
细心的读者在对照上面的原始文档集合和下面的倒排索引时会发现文档中有一部分内容不见了,这里涉及到分词技术的具体细节,我后面会讲,这里先重点理解倒排索引结构。
单词 | 倒排列表 |
---|---|
谷歌 | 1,2,3,4,5 |
地图 | <