虽然lucene4很早就出来,但是这里仍然以lucene3.0为基础,理解lucene索引创建的思路:
1. 要记录正向信息
field的数据,fdx,fdt,依次写每个field的即可
词向量,tvx,tvd,tvf
tvf是真正存储的地方,tvx是每个文档一项,具体包含第一个field的位置,其他field只要记录与覅一个field的偏移量即可
2. 记录反向信息
字典信息,tii,tis,通过字典,能够找到frq位置和prx位置
即,term1记录有此文档的倒排链表的位置,以及位置信息的链表
frq是倒排表,首先是倒排表,之后是跳跃表(肯定先放正常的倒排表,有了确定的位置后,方便建跳跃表),一层一层的建。
prx文档类似的
3. 如果自己来实现,如何实现?
(1)针对正向的数据fdx,fdt,就是一个文档的每个field的进来的原始数据,因此,可以直接保存,因为这不需要额外的分析就可以确定,可以直接写到磁盘的,顺序的写。
文档1
文档2
文档3
...
文档n
(2)针对正向信息的tvx,tvd,tvf等,肯定需要等每个field的term分析结束才行,否则不可能得到完整的信息,具体一个词在本文档中的词频,位置信息,也需要分析完term才能确定
field-->term
term->docid,freq,position
(3)tii,tis,frq,prx的形成,只有在一批文档完成后,才能形成,因为只有知道了所有的文档后,按文档id排序,才能构建
tii,tis
frq->docId1,freq1;docId2,freq2
prox->docId1,prox1;docId2,prox2
4. lucene3.0中的实现
剔除掉接口的描述,只看具体的实现,其实很清楚:
--> code: DocFieldProcessor / DocFieldProcessorPerThread
--> code: DocInverter / DocInverterPerThread / DocInverterPerField
--> code: TermsHash / TermsHashPerThread / TermsHashPerField
--> code: FreqProxTermsWriter / FreqProxTermsWriterPerThread / FreqProxTermsWriterPerField
--> code: TermVectorsTermsWriter / TermVectorsTermsWriterPerThread / TermVectorsTermsWriterPerField
--> code: NormsWriter / NormsWriterPerThread / NormsWriterPerField
--> code: StoredFieldsWriter / StoredFieldsWriterPerThread
处理的层次的分类规则:
(1)是所有文档共享还是线程独立
(2)是正向还是反向的处理
所有文档共享:DocFieldProcessor
所有文档的共享(正向):StoredFieldsWriter
所有文档的共享(反向):DocInverter
线程的入口:DocFieldProcessorPerThread
线程的处理(正向):StoredFieldsWriterPerThread
线程的处理(反向):DocInverterPerThread
4.1 线程的处理(正向):StoredFieldsWriterPerThread
(1)DocumentsWriter有统一的内存管理
(2)每个线程写一个文档时,首先从池中获取一个内存块,写信息
(3)写文档结束后,直接将正向的fdt和fdx写到磁盘上,重用内存块
多个段之间的正向fdt和fdx是可以共享一个文件的。例如没有提交一批文档之前,如果内存满了,那么先flush,会生成tii,tis和frq,prx等。
之后后续commit了,会生成另一个段的tii,tis等,但是fdt和fdx是相同的。
4.2 线程的处理(反向):DocInverterPerThread
一个文档的反向信息要缓存的信息有哪些?
(1)term的文本
(2)term对应的docId,freq,prox信息
(3)上述信息的指针
每个field的有一个缓存的term的hash数组:此hash数组的对象,包含了指针信息:term的文本的指针;term对应的prox信息(遇见一次,记录一次)
后续的文档:当遇到同样的一个term,文本重用,同样的缓存frq,prox即可。
4.3 方向信息的生成:通过flush到磁盘时,从缓存中生成。