2012-02-03 93 views
4

與Lucene索引工作,我有一個標準的文檔格式,看起來是這樣的:Lucene的3.5自定義有效載荷

Name: John Doe 
Job: Plumber 
Hobby: Fishing 

我的目標是一個有效載荷附加到將舉行工作領域有關管道的其他信息,例如維基百科鏈接到管道文章。我不想把有效載荷放在其他地方。最初,我找到了一個涵蓋我想要做的事情的例子,但它使用了Lucene 2.2,並沒有更新來反映令牌流api中的更改。 經過一番更多的研究,我想出了這個小怪物爲這個領域構建自定義標記流。

public static TokenStream tokenStream(final String fieldName, Reader reader, Analyzer analyzer, final String item) { 
     final TokenStream ts = analyzer.tokenStream(fieldName, reader) ; 
     TokenStream res = new TokenStream() { 
      CharTermAttribute termAtt = addAttribute(CharTermAttribute.class); 
      PayloadAttribute payAtt = addAttribute(PayloadAttribute.class); 

      public boolean incrementToken() throws IOException { 
       while(true) { 
        boolean hasNext = ts.incrementToken(); 
        if(hasNext) { 
         termAtt.append("test"); 
         payAtt.setPayload(new Payload(item.getBytes())); 
        } 
        return hasNext; 
       } 
      } 

     }; 
     return res; 
    } 

當我使用令牌流並遍歷所有結果時,在將它添加到字段之前,我看到它成功地將術語和有效負載配對。在流上調用reset()之後,我將它添加到文檔字段並索引文檔。但是,當我打印出文檔並使用Luke查看索引時,我的自定義標記流沒有完成剪切。字段名稱顯示正確,但來自標記流的術語值不會顯示,也不會顯示成功附加有效內容。

這使我2個問題。首先,我是否正確使用了令牌流,如果是的話,爲什麼它不會在我將其添加到域時進行標記?其次,如果我沒有正確使用流,是否需要編寫我自己的分析器。這個例子使用Lucene標準分析器拼湊在一起生成令牌流並寫入文檔。我希望儘可能避免編寫我自己的分析器,因爲我只希望將有效載荷附加到一個字段!

編輯:

調用代碼

TokenStream ts = tokenStream("field", new StringReader("value"), a, docValue); 
     CharTermAttribute cta = ts.getAttribute(CharTermAttribute.class); 
     PayloadAttribute payload = ts.getAttribute(PayloadAttribute.class); 
     while(ts.incrementToken()) { 
      System.out.println("Term = " + cta.toString()); 
      System.out.println("Payload = " + new String(payload.getPayload().getData())); 

     } 
     ts.reset(); 

回答

1

這是很難說爲什麼有效載荷不會被保存,其原因可能在使用您所提出的方法的代碼所在。

最方便的方式來設置有效載荷是在TokenFilter - 我認爲,採用這種方法會給你更清潔的代碼,進而正確地使您的方案工作。我認爲在Lucene源代碼中查看一些這種類型的過濾器是最具說明性的,例如, TokenOffsetPayloadTokenFilter。您可以在test for this class中找到應該如何使用它的示例。

也請考慮一下,如果沒有更好的地方來存儲這些超鏈接比在有效載荷。有效載荷對於例如提高取決於他們的位置或原始文檔的格式的一些術語,詞性......他們的主要目的是爲了影響如何執行搜索,所以它們通常數值,有效的填充,以減少索引大小。

+0

我會在今天晚些時候更新調用代碼的帖子。最終的數據可能不是超鏈接,我試圖讓這個概念起作用,並且超鏈接是我組裝示例時首先想到的第一件事。 :) – FloppyDisk 2012-02-10 18:24:59

+0

您是否研究過我建議的解決方案,即實施'TokenFilter'?它肯定會使代碼更加清潔,並且是在Lucene中執行此類事情的最自然的方式。 – 2012-02-11 16:39:45

+0

對不起,延遲了,我看過了。如果我可以避免,我想避免暫時編寫我自己的分析儀。但是,看起來這就是我所要做的。 – FloppyDisk 2012-02-13 14:21:46

0

我可能失去了一些東西,但是...... 你不需要自定義標記生成附加信息的Lucene的文件關聯。只是存儲是一個未分析的領域。

doc.Add(new Field("fname", "Joe", Field.Store.YES, Field.Index.ANALYZED)); 
doc.Add(new Field("job", "Plumber", Field.Store.YES, Field.Index.ANALYZED)); 
doc.Add(new Field("link","http://www.example.com", Field.Store.YES, Field.Index.NO)); 

然後,您可以像任何其他字段一樣獲取「鏈接」字段。

另外,如果你確實需要一個自定義的標記生成器,那麼你肯定會需要一個定製的分析來實現它,同時爲建立索引和搜索。

+0

我搞砸了,問題是,速度很慢。我無法利用「發佈」列表來檢索一條信息。相反,我必須擊中每個文檔,從索引中加載文檔,然後獲取該字段。花費太多時間。 – FloppyDisk 2012-02-10 18:24:06