全文检索以及Lucene原理的理解

Lucene是一个基于Java的高效的全文检索库,用一句大白话来说,它就是一种用来快速查找单词的工具。
在了解Lucene原理之前我们先了解一下全文检索,那么问题来了,什么叫全文检索
1:什么是全文检索
就我们日常生活中的数据来说,可以分为结构化数据非结构化数据.
所谓结构化数据,就是有固定格式或者有限长度的数据,比如数据库,元数据等。
所谓非结构化数据,就是不定长,无固定格式的数据,比如邮件,word文档等。非结构化数据,也叫全文数据
一般来说,对于结构化数据,因为有一定结构,所以我们可以借助一些算法来搜索,所以搜索地比较快,对于非结构化数据,也就是全文数据,搜索就比较慢了。
因此有人就想,如果能把非结构化数据变成结构化数据就好了。就像我们在字典里找一个词,如果没有拼音和偏旁部首,我们需要一页一页地去翻书找,很费劲,有了拼音和部首,我们就可以很快地找到它了。我们搜索时,结构化的拼音→读音→指向的页数,找到非结构化的数据(字)。
如果我们把非结构化数据提取一部分信息然后重新组织,让它的查找变得有迹可循,有规律,转为结构化数据,我们的搜索应该会变快了吧。而这部分提取出的重新组织的信息就是索引。
所以,什么是全文检索?
先建立索引(Indexing),再对索引进行搜索(Search)的过程就是全文检索。
2:重要问题
2.1 索引里面存什么?
字符串到文件的映射(根据字符串就能找到文档)
2.2 如何创建索引?
原文档→分词,去标点,去停词,大写变小写,变为词根→给索引组件,构造倒排索引
2.3 如何对索引进行搜索?
输入查询语句→词法分析,语法分析,语言处理→搜索索引→根据得到的文档和查询语句的相关性,对结果进行排序
涉及VSM向量空间模型tf-idf算法,后面介绍
3:举个栗子
比如,有两篇文档
D1:我是中国人,中国真好!
D2:我爱中国。
假设现在已经分了词,去了停词什么的(分词的结果不一定对,举个例子说明问题),则两篇文档的关键词如下:
AD1 :【我】【是】 【中国人】【中国】 【真】【好】
AD2 : 【我】【爱】【中国】
则倒排索引结构如下:

关键词 文章号 频次 位置
1 1 1
2 1 1
2 1 2
1 1 2
1 1 8
1 1 9
中国 1 1 6~7
2 1 3~4
中国人 1 1 3~5

Lucene中把词和文章号存在词典文件(Term Dictionary)里面,词典文件里面还存了指向频率文件和位置文件的指针,还有field信息(标题,正文,url等);
把频次存在频率文件(Frequency)里面;
把位置存在位置文件(Position)里面,位置有利于高亮等操作。

然后比如你要找"中国",首先会在索引里面找,找出含有“中国”的文档,然后对这两个文档分别计算和查询语句的相关度,按结果排序,然后返回呈现给用户。
4:什么是倒排索引?
通过文档找词,比如我要在一篇文章中找“南京”,这个叫做正排。而通过词找含有这个词的文档,比如我想在某10篇文档中找哪些文档有“南京”这个词,这个叫做倒排。
倒排索引是一种数据结构,列出每个单词所在的文档和它们在每篇文档中出现的频次,优化的倒排索引一般还要包括单词在出现文档中的位置,这为搜索短语提供了可能。用户按关键词查询时,系统只需要在索引中找到该单词,就可以找到对应的文档。
比如,当用户输入查询关键词“迪奥 口红”时,系统可以通过倒排索引查找到所有包含“迪奥”和“口红”的文档,然后,对两个文档集合取交集得到同时出现“迪奥”和“口红”两个单词的文档,再根据位置信息,确定那些“迪奥”恰好出现在“口红”之前的文档,从而得到最终查询结果。
5:怎么计算文档的相关度?
在此引入向量空间模型(Vector Space Model)的概念,基本思想是:整个向量空间由不包含停用词的关键词构成:<t1, t2, …tn>,候选文档D=<a1, a2, …an>, 其中ai(1≤i≤n)为D中 ti 的权重,用户查询语句Q= <b1, b2, …bn>,bi 为Q中 ti 的权重。用户查询语句与候选文档的相关度可以由很多种方法求得,比如点积法,余弦法,Dice法, Jaccard方法等。
这里用的是余弦法,
全文检索以及Lucene原理的理解
文档向量和查询向量里的权重有很多种计算方式,Lucene里面用的是tf-idf算法。
全文检索以及Lucene原理的理解
这是最简单的方式,有的还加了很多权重,中心思想就是这样。
好像后面的Lucene还用到了什么BM25算法。这里不再研究了。

先写到这里吧。