2012-12-17 76 views
8

要允許用戶使用Lucene 3.5在多個字段中進行搜索,我當前爲要搜索的每個字段創建並添加QueryParserDisjunctionMaxQuery。這在使用作爲默認操作員時很有用,但我現在想要將默認操作員更改爲以獲得更準確(更少)的結果。Lucene:使用默認運算符搜索多個字段= AND

問題是,queryParser.setDefaultOperator(QueryParser.AND_OPERATOR)錯過了許多文件,因爲所有術語必須在至少1個字段。

例如,考慮文檔的以下數據:title field =「Programming Languages」,body field =「Java,C++,PHP」。如果用戶要搜索Java編程此特定文檔將不會包含在結果中,因爲標題或主體字段包含查詢中的所有術語(儘管它們組合在一起)。我希望爲上述查詢返回此文檔,但不希望查詢HTML編程

我已經考慮了一個catchall字段,但我有一些問題。首先,用戶經常在他們的查詢中包含每個領域的術語(作者:賬單),這對於一個查詢字段來說是不可能的。另外,我用FastVectorHighlighter突出顯示某些字段,這些字段需要對它們進行索引和存儲。因此,通過添加一個catchall字段,我將不得不索引大部分相同的數據兩次,這是時間和空間消耗。

任何想法?

+0

關於對catchall字段進行索引,是否觀察到引起關注的時間/空間命中?我的經驗是索引特定存儲字段中的相同數據,然後添加到廣義索引字段對性能或索引大小的影響相當小。 – femtoRgon

+0

另外,我不知道結束查詢的結構是什麼樣子。特別是如何設置dis-max查詢。容易殺​​死你獲得有意義的分數的能力。 – femtoRgon

+0

@femtoRgon disjunctionMaxQuery結構如下所示:'((title:java title:programming)|(body:java body:programming))〜0.2'您提到了一個很好的觀點,即添加catchall字段可能對遠程時間影響不大/空間有關。我當然認爲它,但決定反對它,因爲我還想保持按字段搜索的能力,例如作者:賬單。用戶不僅使用此功能,而且在幕後使用它。謝謝。 –

回答

6

猜猜我應該多做一點研究。原來MultiFieldQueryParser提供了我正在尋找的確切功能。無論出於何種原因,我創建爲每個字段的QueryParser我想尋找這樣的:

String[] fields = {"title", "body", "subject", "author"}; 
QueryParser[] parsers = new QueryParser[fields.length];  
for(int i = 0; i < parsers.length; i++) 
{ 
    parsers[i] = new QueryParser(Version.LUCENE_35, fields[i], analyzer); 
    parsers[i].setDefaultOperator(QueryParser.AND_OPERATOR); 
} 

這將導致這樣的查詢:

(+title:java +title:programming) | (+body:java +body:programming) 

...這不是我是什麼看着。現在,我創建一個單一的MultiFieldQueryParser這樣的:

MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_35, new String[]{"title", "body", "subject"}, analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 

這給了我,我一直在尋找查詢:

+(title:java body:java) +(title:programming body:programming) 

感謝@seeta和@femtoRgon的幫助!

2

也許你需要的是布爾查詢的組合,捕獲字段和術語的不同組合。在你給定的例子中,查詢可能是 -

(標題:Java AND body:programming)OR(標題:programming AND body:Java)。

我不知道是否有一個現有的Query類爲您自動生成此類,但我認爲這應該是在索引上運行的最終查詢。

+0

我認爲你是在正確的軌道上,雖然我認爲最好是切換AND和OR這樣的權利? (標題:java OR body:java OR subject:java)AND(title:programming OR body:programming OR subject:programming)... [process additional terms] ...我會在完成時發佈我的實現,可能的解決方案。 Thx爲答案。 –

0

您希望能夠從您的評論搜索多個領域同一套條款,那麼問題:

((title:java title:programming) | (body:java body:programming))~0.2 

可能不是最好的實現。

您正在有效地從標題中獲得分數,或者從組合集合中得到正文的分數。在標題和體內編程中擊中java的情況將給出約。等同於在體內對java的打擊並且不會對編程產生影響。

我想一個更好的結構化查詢是:

(title:java body:java)~0.2 (title:programming body:programming)~0.2 

這使得我更有意義,因爲你想要的dismax查詢限制得分上同一術語的多個查詢成長(不同領域),但我相信,你確實希望得分能夠以不同的條件獲得點數。

如果這種查詢結構讓您更好地評分結果,將結果限制爲某個最低分數(返回的最高分數的百分比,而不是簡單的硬編碼值)可能足以防止結果太弱從被看見。


我也還是不會算出來的索引所有領域。這是我之前使用過的一個實現,同時索引了特定的字段和catchall字段,從而允許通用查詢和特定的單字段查詢。索引存儲對於未存儲的條款往往非常精簡,如果您發現自己不得不創建大而複雜的查詢以彌補索引存儲空間,它通常會有助於提高性能。

如果你真的想確保它需要最少的存儲,你甚至可以關閉TermVectors該字段:

new Field(name, value, Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO); 

雖然我不知道有多大的差別,將真正使的。