0

要するに、複数のフィールドと値のマッピングを 1 つのインデックスから結果のインデックスに交換する必要があります。

以下はシナリオです。

インデックス 1構造 [フィールド => 値] [保存]

Doc 1    
keys => keyword1;    
Ids => id1, id1, id2, id3, id7, id11, etc.. 

Doc 2    
keys => keyword2;    
Ids => id3, id11, etc..

インデックス 2構造 [フィールド => 値] [保存]

Doc 1    
ids => id1    
keys => keyword1, keyword1

Doc 3    
ids => id3    
keys => keyword1, keyword2, etc..

結果のインデックスでは、keys<->idsマッピングが逆になっていることに注意してください。

時間の複雑さの観点から、これを達成するための最も効果的な方法は何だと思いますか? ..

私が考えることができる唯一の方法はそれです..

1) index1Reader.terms();    
2) Process only terms belonging to "Ids" field    
3) For each term, get TermDocs    
4) For each doc, load it, get "keys" field info    
5) Create a new Lucene Doc, add 'Id', multi Keys, write it to index2.     
6) Go to step 2.

フィールドが保存されているので、それを行う方法は複数あると確信しています。

パフォーマンステクニックがあれば教えてください。Index1 のサイズが最大 6GB であることを考えると、わずかな改善でも私のシナリオでは大きな影響があります。

総数 固有のキーワード数: 1,800 万。総数 一意の ID の数: 90 万

興味深い更新

最適化 1

  • 新しいドキュメントを追加する際、複数の重複する 'Field' オブジェクトを作成する代わりに、" " 区切り文字を使用して単一の StringBuffer を作成し、全体を単一の Field として追加すると、最大 25% 改善されるようです。

更新 2: コード

    public void go() throws IOException, ParseException {
    String id = null;
    int counter = 0;
    while ((id = getNextId()) != null) { // this method is not taking time..
        System.out.println("Node id: " + id);
        updateIndex2DataForId(id);
        if(++counter > 10){
            break;
        }
    }
    index2Writer.close();
}

private void updateIndex2DataForId(String id) throws ParseException, IOException {
    // Get all terms containing the node id
    TermDocs termDocs = index1Reader.termDocs(new Term("id", id));
    // Iterate
    Document doc = new Document();
    doc.add(new Field("id", id, Store.YES, Index.NOT_ANALYZED));
    int docId = -1;        
    while (termDocs.next()) {
        docId = termDocs.doc();
        doc.add(getKeyDataAsField(docId, Store.YES, Index.NOT_ANALYZED));            
    }
    index2Writer.addDocument(doc);
}

private Field getKeyDataAsField(int docId, Store storeOption, Index indexOption) throws CorruptIndexException,
        IOException {
    Document doc = index1Reader.document(docId, fieldSelector); // fieldSel has "key"
    Field f = new Field("key", doc.get("key"), storeOption, indexOption);
    return f;
}
4

1 に答える 1

0

FieldCacheの使用法は魅力のように機能しました...しかし、ヒープ上のすべてのフィールドに対応するために、RAMをますます割り当てる必要があります。

上記のupdateIndex2DataForId()を次のスニペットで更新しました。

private void updateIndex2DataForId(String id) throws ParseException, IOException {
    // Get all terms containing the node id
    TermDocs termDocs = index1Reader.termDocs(new Term("id", id));
    // Iterate
    Document doc = new Document();
    doc.add(new Field("id", id, Store.YES, Index.NOT_ANALYZED));
    int docId = -1;
    StringBuffer buffer = new StringBuffer();
    while (termDocs.next()) {
        docId = termDocs.doc();
        buffer .append(keys[docId] + " "); // keys[] is pre-populated using FieldCache                 
    }
    doc.add(new Field("id", buffer.trim().toString(), Store.YES, Index.ANALYZED));   
    index2Writer.addDocument(doc);
}

String[] keys = FieldCache.DEFAULT.getStrings(index1Reader, "keywords");

それはすべてをより速くしました、私はあなたに正確な測定基準を言うことができません、しかし私は非常に実質的であると言わなければなりません。

これで、プログラムは少し妥当な時間で完了します。とにかく、さらなるガイダンスは大歓迎です。

于 2012-08-01T05:12:23.320 に答える