2013-11-14 133 views
0

我想建立一個應用程序,實現了Lucene索引的搜索系統。現在索引已經建好了,我可以在索引上搜索文檔,並且一切似乎都正常,但是當我使用許多文檔中使用的字段進行搜索時,分析器只返回一些文檔。我試圖使用盧克進行相同的搜索,並採用相同的方式。Lucene的搜索跳過一些結果

例如:我的索引有2個字段:

字段A:唯一的標識符。 字段B:一個字符串。

第一示例:

我們有5個文件:

文件1:FIELDA:1; FieldB:hello world

Doc 2:FieldA:2; FieldB:你好,世界!

Doc 3:FieldA:3; FieldB:hello world

Doc 4:FieldA:4; FieldB:任何東西

Doc 5:FieldA:5; FieldB:世界你好

當我作出這樣一個搜索「B:Hello World」的應該返回文件1,3和5,但它只返回1和3

當我作出這樣一個搜索「A:5」返回文檔5,字段B的值爲「hello world」。

第二實例:(一個令牌)

文件6:FIELDA:6; FieldB:token

Doc 7:FieldA:7; FieldB:token

Doc 8:FieldA:8; FieldB:TOKEN

文件9:FIELDA:9 FieldB:令牌

當我搜索FieldB: 「令牌」 它只返回文檔6和Doc 9.我能找到文件的唯一方法是7通過其FieldA進行搜索。

我使用的是WhitespaceAnalyzer,並且這兩個字段都是NOT_ANALYZED。

IndexGenerator主要

... 

IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED);; 
writer.setRAMBufferSizeMB(200); 

List<Work> works = getWorks(); //Retrieves the information from the DB 

for (Work work: works) { 

    Document luceneDocument = createLuceneDocument(work); 
    writer.addDocument(luceneDocument); 

} 
writer.commit(); 

... 

CreateLuceneDocument方法:

private static Document createLuceneDocument(Work work) { 

try { 
    Document luceneDoc = new Document(); 

    ... 

    Field id = new Field("ID", work.getId(),Field.Store.YES,Field.Index.NOT_ANALYZED); 
    luceneDoc.add(id); 

    Field name = new Field("NAME", work.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED); 
    luceneDoc.add(name); 

    ... 

    return document; 

    } 
    catch (LuceneException e) { 
     ... 
    } 
} 

我注意到,未返回的文檔具有低分值。假設這是索引創建時的問題,因爲盧克的行爲與應用程序的行爲相同,我在做什麼錯了?

提前致謝!

+0

我沒有看到你的例子中會出現這樣的問題。我也不明白你怎麼能得到一個文件的分數,而你的查詢沒有找到。也許一些更多的信息是有用的,比如你的搜索代碼,以及關於這個問題實際發生的數據的一些進一步的信息? – femtoRgon

+0

謝謝@femtoRgon!這個例子是解釋發生的最簡單的方法。真實指數超過12個字段,比例子更復雜。 正如我在第一篇文章中所說,即使這些字段滿足搜索請求,Luke也不會顯示這些文檔。所以,問題應該在索引生成過程中。 我將添加更多關於索引生成的信息。 – user2993510

+0

你在哪裏看到「未返回的文檔具有低分值」? – groverboy

回答

1

Lucene會將搜索表達式B:hello world解析爲B:hello D:world,這是一個表達式。這裏D是默認搜索字段,可能是您在對@ femtoRgon答案的評論中提到的另一個Field

我猜測結果包括文檔1和3,因爲它們與字段D中的標記「世界」相匹配,但是此標記在文檔5字段D中不存在。但是,只有默認搜索運算符爲OR不是,因爲B:hello不能匹配這些文件。

您可能會通過使用短語表達式得到您期望的結果:B:"hello world"。但你不可以; WhitespaceAnalyzer將在構建Query對象時將此短語分解爲兩個令牌。

您可以使用KeywordAnalyzer作爲字段B來解決問題,如我的answer to another question中所述。

+0

我在只有1個標記的字段中以及具有多個標記的字段中面臨此問題。我正在嘗試使用KeywordAnalyzer與盧克一起搜索,但是我得到了相同的結果,也許是因爲索引是使用WhitespaceAnalyzer生成的,但它是否影響到1個標記字段?感謝您的幫助@groverboy! – user2993510

+0

@ user2993510取決於「1令牌字段」的含義。需要說明的是,如果字段B,值爲「hello world」的值是用NOT_ANALYZED創建的,那麼該字段有1個標記[hello world]。如果字段C的值「hello world」是使用'ANALYZED'創建的,那麼該字段有2個標記[hello] [world]。 – groverboy

+0

@ user2993510請給出一個你試過用'KeywordAnalyzer'使用Luke的例子搜索表達式? – groverboy

1

我想給你我的懷疑,我想。您說您正在使用WhitespaceAnalyzer,但由於您的字段爲NOT_ANALYZED,該分析程序對索引內容沒有任何作用。它們被完全按原樣編入索引,作爲單個標記。

如果您將索引值「hello there」,在「hello」上搜索TermQuery將找不到任何內容。如果您編入索引「你好」,「你好!」,甚至「你好」,它也不會找到任何東西。這將是大小寫,標點符號,空格等敏感,並且需要匹配整個輸入。所以我懷疑你的未找到的文件在這些方面有問題。

+0

這是正確的@femtoRgon,我想這些字段被索引爲一個單一的標記,因爲我正在使用另一個'Field'來使用不同的標記索引相同的值。問題是我正在搜索「hello world」,並且只找到了3個文檔中的2個(我已經對該示例進行了一些更改以闡明此問題)。再次感謝! – user2993510

+0

+1 @femtoRgon幫助我回答一個不太清楚的問題。 – groverboy