Lucene创建索引源码分析

当用户往Lucene中添加一个文档时,Lucene会基于该文档创建倒排索引,具体是以文档中的字段Field为单位进行逐个处理的。

大致流程就是对文档中的内容以Field为单位,进行分词处理,并基于处理后的分词(term)建立倒排索引。lucene中不管对文档,还是对字段进行处理,实际上都是在DefaultIndexingChain中处理的。

1 创建DefaultIndexingChain对象

DefaultIndexingChain对象在整个索引创建阶段仅存在一个。在创建DefaultIndexingChain对象的时候,比较重要的就是持有一个TermsHash对象

public DefaultIndexingChain(DocumentsWriterPerThread docWriter) throws IOException {
   
    ...
    TermsHash termVectorsWriter = new TermVectorsConsumer(docWriter);
    //创建一个TermsHash对象
    this.termsHash = new FreqProxTermsWriter(docWriter, termVectorsWriter);
}

TermsHash对象中包含三大内存缓冲池,分别是:

  • intPool缓冲池 : 存储执行bytePool/termBytePool的指针
  • bytePool缓冲池 : 和termBytePool指向同一块内存空间
  • termBytePool缓冲池:存储的是term的[长度,字节值,所在文档ID,词频,偏移量]等信息
TermsHash(DocumentsWriterPerThread docWriter, boolean trackAllocations, TermsHash nextTermsHash) {
   
    this.intPool = new IntBlockPool(docWriter.intBlockAllocator);
    this.bytePool = new ByteBlockPool(docWriter.byteBlockAllocator);
    if (nextTermsHash != null) {
   
        this.termBytePool = this.bytePool;
        nextTermsHash.termBytePool = this.bytePool;
    }
}
2 处理文档processDocument

用户往Lucene中添加一个文档后,Lucene会执行DefaultIndexingChain中的processDocument逻辑,具体代码如下:

public void processDocument() throws IOException, AbortingException {
   
    ...
    while(true) {
   
        //遍历文档中包含的所有字段,以字段为单位,调用processField进行处理
        IndexableField field = (IndexableField)i$.next();
        fieldCount = this.processField(field, fieldGen, fieldCount);
    }
    ...
}
2 处理文档字段processField

在处理每一个字段Field时,Lucene会首先创建一个PerField对象,这个对象的类型是TermsHashPerField,可以看processField方法。

private int processField(IndexableField field, long fieldGen, int fieldCount) throws IOException, AbortingException {
   
    //地段名称
    String fieldName = field.name();
    //字段类型,eg:Stored
    IndexableFieldType fieldType = field.fieldType();
    //声明一个PerField对象
    DefaultIndexingChain.PerField fp = null;
	
    //这里比较重要,在这个方法中创建一个PerField对象
    fp = this.getOrAddField(fieldName, fieldType, true);

    //对字段的值进行分词处理,并建立倒排索引
    fp.invert(field, first);
}

processField方法中比较重要的逻辑就是创建PerField对象和分词建立倒排索引,下面分别来看。

2.1 创建PerField对象

创建PerField对象,是在getOrAddField方法中实现的。getOrAddField方法代码如下。

private DefaultIndexingChain.PerField getOrAddField(String name, IndexableFieldType fieldType, boolean invert) {
   
    
    //方法中比较重要的逻辑就是new一个PerField对象。
    fp = new DefaultIndexingChain.PerField(fi, invert);
    
    //将PerField对象存放在fieldHash数组中
    this.fieldHash[hashPos] = fp;
	
    //返回给上层调用者一个PerField对象
    return fp;
}

new PerField时,会在PerField的构造方法中执行一些额外的逻辑,其中重要的就是将fieldInfo对象中的信息添加到termsHash中,并为每一个Field创建一个TermsHashPerField对象,该对象由PerField持有,并最终存在DefaultIndexingChain的成员变量fieldHash数组中。PerField中的关键代码如下:

public PerField(FieldInfo fieldInfo, boolean invert) {
   
        this.setInvertState();
}

void setInvertS
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值