Lucene索引在文件和内存中的数据结构

本文详细探讨了Lucene的索引结构,包括文件结构中的倒排表和内存中的Field、Term及docId组织。通过示例展示了SimpleTextCodec编码下的索引文件内容,并解释了内存中FST数据结构如何存储Term信息。文章最后以搜索过程为例,阐述了索引在搜索时的状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lucene索引文件结构:

Lucene的索引由多个不同后缀格式的文件组成,本文准确来说应该是lucene索引倒排表的文件结构,具体的组织形式如下:


field fieldName  --域的名称

term termName --term的名称,也就是分出的词

doc docId --文档id,在指定域下,出现指定term(分词)的文档的id

Freq count --term在文档中出现的次数

Pos  --属于第几个分词

Offset --term在文档中的偏移

Payload --payload信息

在不同的codec,文件的后缀名称和存储格式不一样,其中有个simpletextcodec,特别适合用来学习lucene的“黑盒”索引文件,本文就是讲解在SimpleTextCodec编码下的倒排表文件,具体如何指定codec呢?可以参考下面的代码:

 

SimpleTextCodec stc = new SimpleTextCodec();

IndexWriterConfig config = new

IndexWriterConfig(Version.LUCENE_40,analyzer);

config.setCodec(stc);//设置索引的编码格式

 

SimpleTextCodec编码格式下,lucene索引倒排表文件的后缀是.pst,现在我们来索引两个文档来具体看下倒排表的文件内容。

 

Document doc0 = new Document();

doc0.add(new Field("title""title hello title", type));

doc0.add(new Field("content""我是内容", type));

doc0.add(new Field("keyword""我是关键字", type));

writer.addDocument(doc0);

 

Document doc1 = new Document();

doc1.add(new Field("title""title word title title title", type));

doc1.add(new Field("content""我是内容", type));

doc1.add(new Field("keyword""我是关键字", type));

writer.addDocument(doc1);

writer.close();


执行完上面的代码,在索引目录中打开一个.pst后缀的倒排表文件,内容如下:

 

field content

  term 我是内容

    doc 0

      freq 1

      pos 0

    doc 1

      freq 1

      pos 0

field keyword

  term 我是关键字

    doc 0

      freq 1

      pos 0

    doc 1

      freq 1

      pos 0

field title

  term hello

    doc 0

      freq 1

      pos 1

  term title

    doc 0

      freq 2

      pos 0

      pos 2

    doc 1

      freq 4

      pos 0

      pos 2

      pos 3

      pos 4

  term word

    doc 1

      freq 1

      pos 1

END

 

相信不用我来解释了吧,lucene倒排表索引文件的内容一目了然.

 

Lucene索引内存结构:

Lucene索引在内存中的结构主要分三个部分,fieldtermdocId,具体如下:

Field在内存中的组织结构

Field -> fileposition,域名对应在文件中的偏移量,如果是上面的索引,那么这个结构就是:{content:234,keyword:456,title:767}(具体的偏移值是我自己填写的,只是为了说明问题)

 

具体源代码在:org.apache.lucene.codecs.simpletext.SimpleTextFieldsReader,由于篇幅的原因,我这里句挑出重点的几个源代码片段来说明:

TreeMap<String,Long> fields=readFields(in.clone());//从倒排表读取数据,Mapkey值是filed名称,Mapvalue是域在倒排表文件中的偏移(位置)

那我们来看下readFields()方法:

private TreeMap<String,Long> readFields(IndexInput in) throws IOException {

    BytesRef scratch = new BytesRef(10);

    TreeMap<String,Long> fields = new TreeMap<String,Long>();

    

    while (true) {

      SimpleTextUtil.readLine(in, scratch);//in代表.pst倒排表文件输入流

      if (scratch.equals(END)) {

        return fields;

      } else if (StringHelper.startsWith(scratch, FIELD)) {//读取field

        String fieldName = new String(scratch.bytes, scratch.offset + FIELD.length, scratch.length - FIELD.length"UTF-8");

        fields.put(fieldName, in.getFilePointer());

      }

    }

  }

 

注意代码标红的部分.

 

Term在内存中的组织结构

一个叫做FST<input,output>的数据结构,中文名是有穷状态转换器,FSTinputterm的值,output有三个内容:

A)term在倒排表中的偏移量,即在倒排表文件中的位置

B)docFreq,即这个term在多少个文档中出现

C)totalTermFreq,即这个term在文档中出现的总次数

以上面的索引为例,则这个结构是:

FST<{我是内容,258,2,2},{我是关键字,346,2,2},......>,这里”我是内容”是一个term,然后258是这个term在倒排表文件中的偏移量(位置),再接下的两个2分别是这个term出现的文档数和在这些文档中总共出现的次数。

 

具体源代码在:org.apache.lucene.codecs.simpletext.SimpleTextFieldsReaderdloadTerms()方法,读者可以自己去看下这个方法,我这里挑出重点:

 

private FST<PairOutputs.Pair<Long,PairOutputs.Pair<Long,Long>>> fst;//索引在内存中组织结构

 private void loadTerms() throws IOException {

      //由于篇幅原因,省略多行代码

      IndexInput in = SimpleTextFieldsReader.this.in.clone();//倒排表文件

      in.seek(termsStart); //定位文件中的位置,这个值就是上面介绍的field保存的偏移量

     

      while(true) {

        SimpleTextUtil.readLine(in, scratch);

         if (StringHelper.startsWith(scratchTERM)) {//读取到term

          if (lastDocsStart != -1) {

            b.add(Util.toIntsRef(lastTerm, scratchIntsRef), outputs.newPair(lastDocsStart,

                                                                            outputsInner.newPair((long) docFreq, totalTermFreq))); //FST数据结构中添加term数据,lastTermterm的字节数组,lastDocsStart是这个term在倒排表文件中的偏移量,docFreq是出现这个term的文档数,totalTermFreq是这个term在这些文档中总共出现的次数

 

          }

          lastDocsStart = in.getFilePointer();

        }

      }

      fst = b.finish();//term加载到FST完成

}

 

docId在内存中的组织结构

docid -> offset,文档id在索引文件(存储文档数据的文件)中的偏移量.具体的数据结构是:[12,23,37,77......],数组的下标就是文档Id,值就是文档在文件中的偏移量。比如我们要取回文档0的值,那我们根据这个数组找到这个文档在文件中的偏移量是12,然后用随机读定位到文件的这个位置,接着就是read方法取回数据了.源代码在org.apache.lucene.codecs.simpletext.SimpleTextStoredFieldsReadervisitDocument()方法,具体大家就自己去看下吧。

 

lucene搜索时,索引在文件和内存中的状态

现在用一个搜索过程来看下如何加载和使用这些数据,我们使用的搜索条件是:title=hello



Lucene索引在文件和内存中的数据结构大概就是这样,希望本文对你有所帮助


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值