深入理解lucene原理
一:什么是索引,为什么需要索引
对非结构化数据也即对全文数据的搜索主要有两种方法:
一种是顺序扫描法(Serial Scanning):所谓顺序扫描,比如要内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。如果你有一个80G硬盘,如果想在上面到一个内容包含某字符串的文件,不花他几个小时,怕是做不到。Linux下的grep命令也是这一种方式。大家可能觉得这种方法比较原始,但对于小数据量的文件,这种方法还是最直接,最方便的。但是对于大量的文件,这种方法就很慢了。
有人可能会说,对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?
这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引
例如:字典,字典的拼音表和部首检字表就相当于字典的索引
二:索引包含哪些东西
其实是由于我们想要搜索的信息和非结构化数据中所存储的信息不一致造成的。
非结构化数据中所存储的信息是每个文件包含哪些字符串,已知文件,欲求字符串相对容易,也即是从文件到字符串的映射。
而我们想搜索的信息是哪些文件包含此字符串,也即已知字符串,欲求文件,也即从字符串到文件的映射。两者恰恰相反。
于是如果索引总能够保存从字符串到文件的映射,则会大大提高搜索速度。
由于从字符串到文件的映射是文件到字符串映射的反向过程,于是保存这种信息的索引称为反向索引。
左边保存的是一系列字符串,称为词典。每个字符串都指向包含此字符串的文档(Document)链表,此文档链表称为倒排表(Posting List)。
三:索引的创建过程
1.全文索引相对于顺序扫描的优势:一次索引,多次使用
2.创建索引的步骤:
(1)要索引的原文档
(2)将原文档传给分词组件(Tokenizer)
分词组件会做如下事情:(此过程称为Tokenize)
a.将文档分成一个一个的单词
b.去除标点符号
c.去除停词(Stop Word)停词就是语句中无意义的词汇,英语中比如“the”,“a”,“this”等
每一种分词组件(Tokenize)都有一个停词集合
经过分词组件分词后得到的结果称为(词元)Token
(3)将得到的词元传给语言处理组件(Linguistic Processor)
语言处理组件主要对词元进行一些同语言相关的操作
对于英语,语言处理组件主要做如下处理:
a.变为小写(Lowercase)
b.将单词缩减为词根形式如cars->car,这种操作叫做stemming(缩减)
c.将单词转变为词根形式如drove->drive这种操作为lemmatization (转变)
Stemming和lemmatization的异同:
相同之处:Stemming和lemmatization都要使词汇成为词根形式。
两者的方式不同:
Stemming采用的是“缩减”的方式:“cars”到“car”,“driving”到“drive”。
Lemmatization采用的是“转变”的方式:“drove”到“drove”,“driving”到“drive”。
两者的算法不同:
Stemming主要是采取某种固定的算法来做这种缩减,如去除“s”,去除“ing”加“e”,将“ational”变为“ate”,将“tional”变为“tion”。
Lemmatization主要是采用保存某种字典的方式做这种转变。比如字典中有“driving”到“drive”,“drove”到“drive”,“am,is,are”到“be”的映射,做转变时,只要查字典就可以了。
Stemming和lemmatization不是互斥关系,是有交集的,有的词利用这两种方式都能达到相同的转换。
也正是因为有语言转化的处理步骤,才能使搜索drove,而drive也能被搜索出来
语言处理组件处理后得到的是词(term)
(4)将得到的词(term)传给索引组件(Indexer)
a.利用得到的词创建一个字典(term,documentId)
b.对字典按字母排序进行排序
c.合并相同的词(Term)成为文档倒排(Posting List)链表
document frequency即文档频次,表示总共有多少文件包含此词
frequency即词频率,表示文档中包含了几个此词
3.对索引进行搜索
(1)用户输入查询语句and or not查询语句有很多语法。举例lucene AND learned NOT hadoop
(2)对查询语句进行词法分析,语法分析,语言处理。
a.词法分析主要用来识别单词和关键字,如果关键字错误,则视为正常单词如lucene AMD..则视为AMD这个单词
b.语法分析主要是根据查询语句的语法规则形成一颗语法树
c.语言处理与建立索引的语言处理基本相同
(3)搜索索引,得到满足语法树的文档
a.首先,在反向索引表中,分别出包含lucene,learn,hadoop的文档列表
b.其次,对包含lucene,learn的链表进行合并操作,得到既包含lucene 又包含learn的文档链表
c.然后,将此链表与hadoop的文档链表进行差操作,去除包含hadoop 的文档,从而得到既包含lucene,又包含learn,但是不包含hadoop的文档链表
d.得到的链表就是我们需要的文档
(4)根据得到的文档和查询语句的相关性,对结果进行排序
a.计算权重(Term weight)的过程。
b.判断Term之间的关系从而得到文档相关性的过程,也即向量空间模型的算法(VSM)
查询概括:
1.索引过程
1)有一系列被索引文件
2)被索引文件经过语法分析和语言处理形成一系列词(Term)。
3)经过索引创建形成词典和反向索引表。
4)通过索引存储将索引写入硬盘。
2.搜索过程:
a)用户输入查询语句。文档字符串是什么
b)对查询语句经过语法分析和语言分析得到一系列词(Term)。
c)通过语法分析得到一个查询树。
d)通过索引存储将索引读入到内存。
e)利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链
表进行交,差,并得到结果文档。
f)将搜索到的结果文档对查询的相关性进行排序。
g)返回查询结果给用户
4.lucene的索引文件格式
lucene索引结构是有层次结构的,具体如下:
(1)索引:索引全部是是放在同一个文件夹中,这些内容构成了一个完整的lucene索引
(2)段(segment):一个索引可以包括很多段,段与段之间是独立的,新添加新文档可以生成新的段,段与段可以合并具有相同前缀文件的属于同一段,如和segment_5是段的数据文件,也即它们保存了段的属性信息
(3)文档(document):文档是建立索引的基本单位,不同的文档保存在不同的段中,一个段可以包括多篇文档
新添加的文档是单独保存在新生成的段中,随着段的合并,不同的文档合并到同一个段中。
(4)域(field):一篇文档包含不同类型的信息,可以分开索引,比如正题,时间,正文等,都可以保存在不同的域中,不同域的索引方式可以不同
(5)词(term):词是索引的最小单位,是经过词法分析和语言处理后的字符串
lucene的索引结构中,既包括了正向信息,也包括了反向信息
正向信息:按层次保存了从索引一直到词的包含关系,索引(Index)-->段(segment)-->文档(document)-->域(field)-->词(term);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。