2012-05-15 38 views
6

是否可以使用Lucene SpanQuery來查找所有出現的術語「紅色」「綠色」和「藍色」都出現在單個句子中的所有事件?使用Lucene SpanQueries進行句子感知搜索

我的第一個(不完整/不正確)方法是編寫一個分析器,它將一個特殊的句子標記標記和一個句子的開頭放置在與該句子的第一個單詞相同的位置,然後查詢類似於以下:

SpanQuery termsInSentence = new SpanNearQuery(
    SpanQuery[] { 
    new SpanTermQuery(new Term (MY_SPECIAL_SENTENCE_TOKEN)), 
    new SpanTermQuery(new Term ("red")), 
    new SpanTermQuery(new Term ("green")), 
    new SpanTermQuery(new Term ("blue")), 
    }, 
    999999999999, 
    false 
); 

SpanQuery nextSentence = new SpanTermQuery(new Term (MY_SPECIAL_SENTENCE_TOKEN)); 

SpanNotQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 

的問題,當然,是nextSentence是不是真的下一個一句,這是任何句子標記,包括一個在句子termsInSentence匹配。因此這不起作用。

我的下一個方法是創建一個分析器,將令牌放置在句子前(之前第一個詞,而不是與第一個詞相同的位置)。這個問題是我必須考慮由MY_SPECIAL_SENTENCE_TOKEN造成的額外抵消。更重要的是,當我使用天真模式來分割句子時(例如分割爲/\.\s+[A-Z0-9]/),這首先會特別糟糕,因爲當我搜索USS Enterprise時,我將不得不考慮所有(虛假)句子標記

那麼...我該如何處理這個問題呢?

回答

1

我會將每個句子都索引爲一個Lucene文檔,其中包括一個標記該句子來自哪個源文檔的字段。取決於您的源材料,可以接受句子/ LuceneDoc的開銷。

0

其實,看起來你很接近解決方案。我認爲索引結束句子標誌是一種好方法。問題在於你的結束語旗幟​​在你的SpanNearQuery,這是拋棄你的東西。你正在要求它找到一個跨度,其中包含和不包含包含MY_SPECIAL_SENTENCE_TOKEN。查詢自相矛盾,所以當然,它不會找到任何匹配。你真正需要知道的是,三個詞(「紅色」,「綠色」和「藍色」)出現在與MY_SPECIAL_SENTENCE_TOKEN不重疊的範圍內(也就是說,句子標記不出現在這些詞之間計算)。

此外,缺乏在Term構建函數字段名稱將是問題,但Lucene的應該拋出一個異常,抱怨這一點,所以猜測這裏這不是真正的問題。可能是因爲當時寫的Lucene版本並沒有抱怨SpanNears中的不匹配字段,所以也許值得一提。

這似乎工作,對我說:

SpanQuery termsInSentence = new SpanNearQuery(
    new SpanQuery[] { 
     new SpanTermQuery(new Term ("text", "red")), 
     new SpanTermQuery(new Term ("text", "green")), 
     new SpanTermQuery(new Term ("text", "blue")), 
    }, 
    9999, 
    false 
); 

SpanQuery nextSentence = new SpanTermQuery(new Term ("text", MY_SPECIAL_SENTENCE_TOKEN)); 

SpanQuery notInNextSentence = new SpanNotQuery(termsInSentence,nextSentence); 

至於哪裏拆分,而不是使用正則表達式的幼稚做法的句子,我會嘗試使用java.text.Breakiterator。這並不完美,但它做得很好。