注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Lucene源代码分析[13]  

2009-07-06 09:39:21|  分类: Lucene |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

tis = new TermInfosReader(cfsDir, segment, fieldInfos);

    .tis.tii我们已经领教过了,非常不好懂,看一下它的构造函数:

TermInfosReader(Directory dir, String seg, FieldInfos fis)

       throws IOException {

    directory = dir;

    segment = seg;

    fieldInfos = fis;

 

    origEnum = new SegmentTermEnum(directory.openInput(segment

+ ".tis"),

           fieldInfos, false);

    size = origEnum.size;

 

    indexEnum = new SegmentTermEnum(directory.openInput(segment

+ ".tii"),

           fieldInfos, true);

}

    我们看到读tis的对象是origEnum,读.tii的对象是indexEnum

    回忆一下,在SegmentMerger中的mergeTermInfos中的开始几行代码:

int base = 0;

for (int i = 0; i < readers.size(); i++) {

    IndexReader reader = (IndexReader) readers.elementAt(i);

    TermEnum termEnum = reader.terms();

    SegmentMergeInfo smi = new SegmentMergeInfo(base, termEnum, reader);

    base += reader.numDocs();

    if (smi.next())

       queue.put(smi); // initialize queue

    else

       smi.close();

}

    我们看到与termEnum有关的应该是在reader.terms函数中:

public TermEnum terms() {

    return tis.terms();

}

    再列出TermInfosReaderterms函数:

public SegmentTermEnum terms() {

    return (SegmentTermEnum) origEnum.clone();

}

    看来还是有必要仔细看一下SegmentTermEnum的构造函数:

SegmentTermEnum(IndexInput i, FieldInfos fis, boolean isi)

       throws IOException {

    input = i;

    fieldInfos = fis;

    isIndex = isi;

 

    int firstInt = input.readInt();

    if (firstInt >= 0) {

       // original-format file, without explicit format version number

       format = 0;

       size = firstInt;

 

       // back-compatible settings

       indexInterval = 128;

       skipInterval = Integer.MAX_VALUE; // switch off skipTo optimization

 

    } else {

       // we have a format version number

       format = firstInt;

 

       // check that it is a format we can understand

       if (format < TermInfosWriter.FORMAT)

           throw new IOException("Unknown format version:" + format);

 

       size = input.readLong(); // read the size

 

       if (format == -1) {

           if (!isIndex) {

              indexInterval = input.readInt();

              formatM1SkipInterval = input.readInt();

           }

           // switch off skipTo optimization for file format prior to

// 1.4rc2 in order to avoid a bug in

           // skipTo implementation of these versions

           skipInterval = Integer.MAX_VALUE;

       } else {

           indexInterval = input.readInt();

           skipInterval = input.readInt();

       }

    }

}

    我们看到第一个读的是一个int,当时写入的时候第一个写入的是FORMAT,这个值是-2,如果读取的时候发现它的值大于0,说明它是以前的文件格式,看样子,以前第一个才是保存size的,而且也不能skip

    下面是判断是不是高版本的FORMAT,等于-1,注释上写的是1.4的版本skipTo中有一个bug,就不让它skip了。下面是读取indexIntervalskipInterval。但是主要内容是怎么读的呢?我们其实也见到,而且还在mergeTermInfos里面:

while (matchSize > 0) {

    SegmentMergeInfo smi = match[--matchSize];

    if (smi.next())

       queue.put(smi); // restore queue

    else

       smi.close(); // done with a segment

}

    就是这个next函数,看起来很不起眼,进到SegmentMergeInfo中看一下:

final boolean next() throws IOException {

    if (termEnum.next()) {

       term = termEnum.term();

       return true;

    } else {

       term = null;

       return false;

    }

}

    这里的termEnum就是SegmentTermEnum,看一下它的next函数:

public final boolean next() throws IOException {

    if (position++ >= size - 1) {

       termBuffer.reset();

       return false;

    }

 

    prevBuffer.set(termBuffer);

    termBuffer.read(input, fieldInfos);

 

    termInfo.docFreq = input.readVInt(); // read doc freq

    termInfo.freqPointer += input.readVLong(); // read freq pointer

    termInfo.proxPointer += input.readVLong(); // read prox pointer

 

    if (format == -1) {

       //  just read skipOffset in order to increment  file pointer;

       // value is never used since skipTo is switched off

       if (!isIndex) {

           if (termInfo.docFreq > formatM1SkipInterval) {

              termInfo.skipOffset = input.readVInt();

           }

       }

    } else {

       if (termInfo.docFreq >= skipInterval)

           termInfo.skipOffset = input.readVInt();

    }

 

    if (isIndex)

       indexPointer += input.readVLong(); // read index pointer

 

    return true;

}

    把上面的set函数列出来,它们都是TermBuffer类中的函数:

public final void set(TermBuffer other) {

    setTextLength(other.textLength);

    System.arraycopy(other.text, 0, text, 0, textLength);

 

    this.field = other.field;

    this.term = other.term;

}

    看起来是把termBuffer中的内容复制到了prevBuffer中。

    再看read函数:

public final void read(IndexInput input, FieldInfos fieldInfos)

        throws IOException {

    this.term = null; // invalidate cache

    int start = input.readVInt();

    int length = input.readVInt();

    int totalLength = start + length;

    setTextLength(totalLength);

    input.readChars(this.text, start, length);

    this.field = fieldInfos.fieldName(input.readVInt());

}

    回忆一下,我们写的时候第一个写入的是与上一个term有多少相同的字符,第二个写入的是有多少个剩余的字符要写,而totalLength就是这个term的总长度,这里的readChars有必要看一下:

public void readChars(char[] buffer, int start, int length)

       throws IOException {

    final int end = start + length;

    for (int i = start; i < end; i++) {

       byte b = readByte();

       if ((b & 0x80) == 0)

           buffer[i] = (char) (b & 0x7F);

       else if ((b & 0xE0) != 0xE0) {

           buffer[i] = (char) (((b & 0x1F) << 6) | (readByte() & 0x3F));

       } else

           buffer[i] = (char) (((b & 0x0F) << 12)

                  | ((readByte() & 0x3F) << 6) | (readByte() & 0x3F));

    }

}

    它是从start开始写入text的,下面的是与我们以前讲的writeChars是一个逆过徎,再解释清楚一点,text里面可能是有值的,那么start又是重复的开始,也就是每次只写与上一次不同的内容。最后读的VInt是这个Field的序数,再通过fieldName来得到它的名字。

    回到next 函数看读的下一下值readInt,读到的是有包含这个term的文档数量。下面的也没有问题,读到.frq.prx的指针位置。下面就是读skip的事,最后一个如果是索引的话就把针指加上读到的long

    看起来skipIntervalIndexInterval还是很有意思的,讲一下:把我们的测试代码改写成:

public class FieldTest

{

    public static void main( String[] args ) throws Exception

    {

       IndexWriter writer = new IndexWriter( "E:\\a\\", new

SimpleAnalyzer(), true);

       writer.setUseCompoundFile( false );   

       int n = 1000;

       for( int i = 0; i < n; i++ )

       {

           Document doc1 = new Document();

           Field name1 = new Field( "TheField", "hello" + i,

           Field.Store.YES, Field.Index.UN_TOKENIZED,

TermVector.YES );

           doc1.add( name1 );

           writer.addDocument( doc1 );

       }

      

       writer.close();

    }

}

    这里注意,用Field.Index.UNTOKENIZED另一个地方是setUseCompoundFile放前面,以前写错的,但为什么看不出来,自己想一下,也都讲过,我们把.tii.tis列出来,自己用的时候最好也用WinHex之类的,UltraEdit不怎么专业。

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

 

00000000   FF FF FF FE 00 00 00 00  00 00 00 08 00 00 00 80   ????..........?

00000010   00 00 00 10 00 00 FF FF  FF FF 0F 00 00 00 14 00   ......????......

00000020   08 68 65 6C 6C 6F 32 31  32 00 01 EF 01 7F 85 07   .hello212..??

00000030   05 03 33 32 38 00 01 F4  01 80 01 80 07 05 03 34   ..328..??.?...4

00000040   34 33 00 01 F3 01 80 01  80 07 05 03 35 35 39 00   43..??.?...559.

00000050   01 F4 01 80 01 80 07 05  03 36 37 34 00 01 F7 01   .??.?...674..?

00000060   80 01 80 07 05 02 37 39  00 01 FF 01 80 01 80 07   ?.?...79..?.?.?.

00000070   05 03 39 30 34 00 01 FE  01 80 01 80 07            ..904..??.?.

 

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

 

00000000   FF FF FF FE 00 00 00 00  00 00 03 E8 00 00 00 80   ????......?..?

00000010   00 00 00 10 00 06 68 65  6C 6C 6F 30 00 01 00 00   ......hello0....

00000020   05 01 31 00 01 01 01 06  01 30 00 01 01 01 07 01   ..1......0......

00000030   30 00 01 01 01 07 01 31  00 01 02 01 07 01 32 00   0......1......2.

00000040   01 02 01 07 01 33 00 01  02 01 07 01 34 00 01 02   .....3......4...

00000050   01 07 01 35 00 01 02 01  07 01 36 00 01 02 01 07   ...5......6.....

00000060   01 37 00 01 02 01 07 01  38 00 01 02 01 07 01 39   .7......8......9

00000070   00 01 02 01 06 01 31 00  01 02 01 07 01 30 00 01   ......1......0..

00000080   01 01 07 01 31 00 01 02  01 07 01 32 00 01 02 01   ....1......2....

00000090   07 01 33 00 01 02 01 07  01 34 00 01 02 01 07 01   ..3......4......

000000A0   35 00 01 02 01 07 01 36  00 01 02 01 07 01 37 00   5......6......7.

000000B0   01 02 01 07 01 38 00 01  02 01 07 01 39 00 01 02   .....8......9...

000000C0   01 06 01 32 00 01 02 01  07 01 30 00 01 01 01 07   ...2......0.....

000000D0   01 31 00 01 02 01 07 01  32 00 01 02 01 07 01 33   .1......2......3

000000E0   00 01 02 01 07 01 34 00  01 02 01 07 01 35 00 01   ......4......5..

000000F0   02 01 07 01 36 00 01 02  01 07 01 37 00 01 02 01   ....6......7....

00000100   07 01 38 00 01 02 01 07  01 39 00 01 02 01 06 01   ..8......9......

         .tis草草一看,好象是012345……和我们说的两个term前面相同的就不记录是相吻合的,但是仔细一想不对,hello9hello10差两个字符应该是9过后是记录两个数字呀。其实不是这样的,因为我们开始排过序,所以应该是0110100101这样的顺序,也就是hello0hello1hello10hello100……,这里只列出了0x100个。

         我们再看.tii,到0x1E的值,我们以前都看过,我看接着看,第一个还是00是因为上次是第一个位置,所以没有写入term,这次依然与前面的term相同字符数为008hello212的长度。2128hello212字符,接下来的00Field序数,01是包含这个词的Document频率。EF 01 7F 85 07,分别是239128901。到底怎么样可以很快地算出来是这几个值,我也没想过,但感觉不是很难。

         我把.frq.prx列出来:

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

 

00000000   01 03 15 C9 01 CB 01 CD  01 CF 01 D1 01 D3 01 D5   ...???????

00000010   01 D7 01 D9 01 DB 01 17  DD 01 DF 01 E1 01 E3 01   .???.????

00000020   E5 01 E7 01 E9 01 EB 01  ED 01 EF 01 19 F1 01 F3   ??????.??

00000030   01 F5 01 F7 01 F9 01 FB  01 FD 01 FF 01 81 02 83   .??????.??

00000040   02 1B 85 02 87 02 89 02  8B 02 8D 02 8F 02 91 02   ..???????

00000050   93 02 95 02 97 02 1D 99  02 9B 02 9D 02 9F 02 A1   ???.?????

00000060   02 A3 02 A5 02 A7 02 A9  02 AB 02 1F AD 02 AF 02   .?????.??

00000070   B1 02 B3 02 B5 02 B7 02  B9 02 BB 02 BD 02 BF 02   ????????

00000080   21 C1 02 C3 02 C5 02 C7  02 C9 02 CB 02 CD 02 CF   !????????

00000090   02 D1 02 D3 02 23 D5 02  D7 02 D9 02 DB 02 DD 02   .??#?????

000000A0   DF 02 E1 02 E3 02 E5 02  E7 02 25 E9 02 EB 02 ED   ?????%???

000000B0   02 EF 02 F1 02 F3 02 F5  02 F7 02 F9 02 FB 02 27   .???????'

000000C0   FD 02 FF 02 81 03 83 03  85 03 87 03 89 03 8B 03   ??.??????

000000D0   8D 03 8F 03 05 29 91 03  93 03 95 03 97 03 99 03   ??.)?????

000000E0   9B 03 9D 03 9F 03 A1 03  A3 03 2B A5 03 A7 03 A9   ?????+???

000000F0   03 AB 03 AD 03 AF 03 B1  03 B3 03 B5 03 B7 03 2D   .???????-

00000100   B9 03 BB 03 BD 03 BF 03  C1 03 C3 03 C5 03 C7 03   ????????

 

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

 

00000000   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000030   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000090   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000000A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000000B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000000C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000000D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000000E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000000F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000100   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

         .prx没什么好讲的,因为每个词就在一个Document中出现,所以它总是0.frq其实也没什么好讲的,只是我自己数数数错了,现在讲一下,

                   0                1                10              100            101            102

<<1            0                2                20              200            202            204

+1              1                3                21              201            203            205

VInt           1                3                15              C9 01        CB 01        CD 01

 

 

 

 

  评论这张
 
阅读(1299)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017