欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

【Lucene3.0 初窺】索引創建(2):DocumentWrite

系統 1612 0

上接 《索引創建(1): IndexWriter索引器》

?

1.3?? 索引創建過程

?

DocumentsWriter是由IndexWriter調用來負責對多個document建立索引的核心類,但整個索引過程并不是由一個對象來完成的。而是有一系列的對象組成的處理鏈(IndexingChain)來完成的(這個過程就像流水線生產汽車)。 下面是DocumentWriter開始建立索引的源代碼。

    //由IndexWriter調用的方法
boolean addDocument(Document doc, Analyzer analyzer){
      return updateDocument(doc, analyzer, null);
}

boolean updateDocument(Document doc, Analyzer analyzer, Term delTerm){
    final DocumentsWriterThreadState state = getThreadState(doc, delTerm);
    final DocState docState = state.docState;
    docState.doc = doc;
    docState.analyzer = analyzer;
    boolean success = false;
    try {
          //調用處理鏈的源頭DocFieldProcessorPerThread開始對Document對象建立索引結構
          final DocWriter perDoc = state.consumer.processDocument();

          finishDocument(state, perDoc);
          success = true;
     } 
      .......
} 

  

?

1.3.1? 第一車間——DocFieldProcessorPerThread

?

DocFieldProcessorPerThread類是索引創建處理鏈的第一步。其基本任務:將document對象原料中所有相同名字的field合并成一個 DocFieldProcessorPerThread對象 ,然后更新FieldInfo信息,最后對不同名字的Field構成一個 DocFieldProcessorPerThread[]對象數組。這個數組就是下一個車間DocInverterPerField要加工的原料了。

?

DocFieldProcessorPerThread類完成第一步處理的核心方法就是processDocument()。在介紹這個方法之前,我們先來看看兩個重要的類DocFieldProcessorPerField和FieldInfo

?

(1) DocFieldProcessorPerField 類是一個合并了相同名字Field的類(可見下圖黃色區域)。它是后面 DocInverterPerField 要處理的單位原料。源碼如下:

    final class DocFieldProcessorPerField {

      final DocFieldConsumerPerField consumer;
     //記錄field的名字、是否要檢索,是否要存儲等信息
     final FieldInfo fieldInfo;
     //指向下一個DocFieldProcessorPerField的指針
     DocFieldProcessorPerField next;
     int lastGen = -1;
     //包含相同名字的field的數量
     int fieldCount;
     //包含的相同名字的field
     Fieldable[] fields = new Fieldable[1];

    public DocFieldProcessorPerField(final DocFieldProcessorPerThread perThread, final FieldInfo fieldInfo) {
         this.consumer = perThread.consumer.addField(fieldInfo);
         this.fieldInfo = fieldInfo;
    }

    public void abort() {
         consumer.abort();
    }
}

  
?

(2) FieldInfo 類并不是指一個Field的全部信息,而是相同名字的Field合并之后的信息。合并過程重要通過update()方法將Field的其他不同屬性統一起來(可見下圖藍色區域)。部分源碼如下:

    final class FieldInfo {
    //Field的相同名字
    String name;
    //是否要索引
    boolean isIndexed;
    //編號
    int number;
    ....
    //構造器
    FieldInfo(..){
    ...
    } 
    //FieldInfo更新的準則是:
    //原來的Field和新的Field有一個要索引(isIndexed=true),則更新后的也索引。
    //如果新的Field不需要索引,則其他操作指標不變
    //如果新的Field需要索引,則只要有一個操作指標為真,就更新后的也為真
    void update(...){
    ...
    }
}
  
?

下面我們重點看看processDocument()方法是如何把Document對象加工成DocFieldProcessorPerThread[]數組的。

    final class DocFieldProcessorPerThread extends DocConsumerPerThread {
//存儲最后處理的結構:DocFieldProcessorPerField[]數組
DocFieldProcessorPerField[] fields = new DocFieldProcessorPerField[1];
int fieldCount;

//以Field名字作為關鍵字的DocFieldProcessorPerField哈希表結構
DocFieldProcessorPerField[] fieldHash = new DocFieldProcessorPerField[2];


/**
 * 擴大DocFieldProcessorPerField的Hash表容量
 * 每一次擴大到原來容量的2倍,并且將原來存儲的DocFieldProcessorPerField對象順序移動到Hash的最大位置處
 * 比如:原來的容量為2,擴大之后的容量為4,將fieldHash[1]->fieldHash[3],fieldHash[0]->fieldHash[2]
 */
private void rehash() {
....
}

/**
 *第一加工車間處理核心流程
 */
public DocumentsWriter.DocWriter processDocument() {
    //初始化各項數據
    consumer.startDocument();
    fieldsWriter.startDocument();

    //要處理的document對象
    final Document doc = docState.doc;
    assert docFieldProcessor.docWriter.writer.testPoint("DocumentsWriter.ThreadState.init start");

    //記錄處理過程中生成的DocFieldProcessorPerField的數量
    fieldCount = 0;

    //當前的DocFieldProcessorPerField
    final int thisFieldGen = fieldGen++;

    final List<Fieldable> docFields = doc.getFields();
    final int numDocFields = docFields.size();

    for(int i=0;i<numDocFields;i++) {
        //得到doc的每個Field
        Fieldable field = docFields.get(i);
        final String fieldName = field.name();

        //以Field的名字為key,定位到fieldHash[]的位置號hashPos
        final int hashPos = fieldName.hashCode() & hashMask;
        //確定fieldHash[]上指定的hashPos位置是否已經有了數據,也就是是否產生沖突
        DocFieldProcessorPerField fp = fieldHash[hashPos];
        //如果Field的名字不同,但fieldHash[]的hashPos位置產生了Hash沖突,則采用Hash鏈表結構加入到沖突位置上的鏈表末尾。
        while(fp != null && !fp.fieldInfo.name.equals(fieldName))
             fp = fp.next;
        //如果fieldHash[]的hashPos位置上沒有數據,則將新的Field包裝成DocFieldProcessorPerField對象加入到Hash表中
        if (fp == null) {
            FieldInfo fi = fieldInfos.add(fieldName, field.isIndexed(), field.isTermVectorStored(),field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(),field.getOmitNorms(), false, field.getOmitTermFreqAndPositions());

            fp = new DocFieldProcessorPerField(this, fi);
            fp.next = fieldHash[hashPos];
            fieldHash[hashPos] = fp;
            totalFieldCount++;
            //如果DocFieldProcessorPerField的Hash表存儲總數量已經嘗過了總容量的1/2,則擴大容量
            if (totalFieldCount >= fieldHash.length/2)
                rehash();
         }else{ //如果產生了沖突,并且沖突位置上的Field的名字與要加入的Field名字相同,則更新沖突位置上的FieldInfo
             fp.fieldInfo.update(field.isIndexed(), field.isTermVectorStored(),
                            field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(),
                            field.getOmitNorms(), false, field.getOmitTermFreqAndPositions());
         }
      
          //如果具有相同名字的Field,則將同名的Field合并到同一個DocFieldProcessorPerField中的Fieldable[]中
          if (thisFieldGen != fp.lastGen) {
               fp.fieldCount = 0;
               //如果fields[]已經存滿,則擴大2倍的fields[]的容量
               if (fieldCount == fields.length) {
               final int newSize = fields.length*2;
               DocFieldProcessorPerField newArray[] = new DocFieldProcessorPerField[newSize];
               System.arraycopy(fields, 0, newArray, 0, fieldCount);
               fields = newArray;
           }
        
           fields[fieldCount++] = fp;
           fp.lastGen = thisFieldGen;
        }
        //如果具有相同的Field名字,而DocFieldProcessorPerField中的Fieldable[]已經存滿,則擴大2倍的此數組容量用于存放相同名字的Field
        if (fp.fieldCount == fp.fields.length) {
           Fieldable[] newArray = new Fieldable[fp.fields.length*2];
           System.arraycopy(fp.fields, 0, newArray, 0, fp.fieldCount);
           fp.fields = newArray;
        }
      
        fp.fields[fp.fieldCount++] = field;
        if (field.isStored()) {
            fieldsWriter.addField(field, fp.fieldInfo);
        }
   }
   //將fields數組按field名字排序
   quickSort(fields, 0, fieldCount-1);
   //調用下一加工車間DocInverterPerField對每個DocFieldProcessorPerField對象進行處理
   for(int i=0;i<fieldCount;i++)
        fields[i].consumer.processFields(fields[i].fields, fields[i].fieldCount);

    .......
}
  
?

用個圖例來說明一下DocFieldProcessorPerThread類所做的工作。我們拿《 索引創建(1):IndexWriter索引器 》1.1節前期工作中的doc1來作為DocFieldProcessorPerThread的原料。

?

原料:Document doc1 (為了說明相同Field的合并工作,我們加了一個相同名字,值不同的content Field)

????? Field name ??????? Field value ? isIndex ? isStore
???????? name ??????????????? 1 ???? false ???? true
???????? path ????? e:\\content\\1.txt ???? false ???? true
??????? content The lucene is a good IR. I hope I can lean. ???? true ???? true
??????? content Lucene 3.0 like a teacher. I love it.
???? true ???? true

?

半成品: DocFieldProcessorPerField[] fields

注意,上圖中的DocFieldProcessorPerField的next域都指向了null。其實,如果有Field1的名字name1與Field2的名字name2滿足? HashCode(name1)=HashCode(name2) && !name1.equals(name2) 的情況下。Field2所構成的DocFieldProcessorPerField對象將加在Field1所構成的DocFieldProcessorPerField對象的next鏈表后面。這種組織方法便于我們在后面要講到的建立倒排索引的處理。

?

總結: ? DocFieldProcessorPerThread 類的作用就是把Document對象加工成 DocFieldProcessorPerField [] (上圖黃色區域) 。然后把每個 DocField ProcessorPerThread .Fieldable[] (上圖紅色區域)

交給第二車間 DocInverterPerField processFields ( 《索引創建(3):DocmentWriter 處理流程二》 )方法來完成了。

?

【Lucene3.0 初窺】索引創建(2):DocumentWriter 處理流程一


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 男女啪啦猛视频免费 | 日本黄视色视频在线观看 | 噜噜噜动态图超猛烈 | 日韩亚洲欧美视频 | 久久中字 | 日韩亚洲一区中文字幕在线 | 久草视频在线资源 | 妞干网免费在线观看 | 国产视频二 | 伊人欧美 | 在线国产一区 | 一级做一级爱a做片性视频视频 | 青青草华人在线 | 欧美性猛交一区二区三区精品 | 波多野结衣一区二区 | 国99久9在线 | 免费 | 久久久久久久av | 魔法骑士在线观看免费完整版高清 | 久热国产精品视频 | 天天综合色天天综合 | 在线三级网址 | 国产精品69人妻无码久久久 | 精品国产18久久久久久二百 | 夜夜视频 | 91免费版在线观看 | 欧美视频网站免费看 | 亚洲欧美第一视频 | 日韩a级片 | 电家庭影院午夜 | 日韩av中文 | 国产91福利在线精品剧情尤物 | 国产99一区二区 | 国产伦精品 | 99热这里都是国产精品 | A片扒开双腿猛进入免费观看 | 成年网站视频在线观看 | 成人小视频在线观看 | 国产成人精品福利网站在线观看 | 91影院 | 欧美二区视频 | 青青草视频免费观看 |