2013-01-22 61 views
1

我們正在使用搜索術語字符串構建一個bool查詢來搜索我們的Lucene索引。我希望這些字符串可以使用標準分析器進行分析,標準分析器是我們用於索引的分析器。例如,foo-bar 1-2-3應該拆分爲foo,bar,1-2-3,因爲Lucene doc指出連字符會導致數字保持在一起,但是要被標記化的單詞。做這個的最好方式是什麼?使用標準分析器磨砂Lucene搜索術語

目前我正在通過QueryParser運行搜索條件字符串。

QueryParser parser = new QueryParser("", new StandardAnalyzer()); 
Query query = parser.parse(aSearchTermString); 

問題在於插入了引號。例如,foo-bar 1-2-3變爲"foo bar",1-2-3,它不會返回任何內容,因爲Lucene會將標記爲foo-bar的標記爲foobar

我絕對不想通過刪除引號replace來破解這種情況,因爲我覺得我可能錯過了某些東西或者做了不正確的事情。

回答

1

我實際上獲得了StandardAnalyzer的不同結果。考慮這個代碼(使用Lucene V4):

public class Tokens { 

    private static void printTokens(String string, Analyzer analyzer) throws IOException { 
     System.out.println("Using " + analyzer.getClass().getName()); 
     TokenStream ts = analyzer.tokenStream("default", new StringReader(string)); 
     OffsetAttribute offsetAttribute = ts.addAttribute(OffsetAttribute.class); 
     CharTermAttribute charTermAttribute = ts.addAttribute(CharTermAttribute.class); 

     while(ts.incrementToken()) { 
      int startOffset = offsetAttribute.startOffset(); 
      int endOffset = offsetAttribute.endOffset(); 
      String term = charTermAttribute.toString(); 
      System.out.println(term + " (" + startOffset + " " + endOffset + ")"); 
     } 
     System.out.println(); 
    } 

    public static void main(String[] args) throws IOException { 
     printTokens("foo-bar 1-2-3", new StandardAnalyzer(Version.LUCENE_40)); 
     printTokens("foo-bar 1-2-3", new ClassicAnalyzer(Version.LUCENE_40)); 

     QueryParser standardQP = new QueryParser(Version.LUCENE_40, "", new StandardAnalyzer(Version.LUCENE_40)); 
     BooleanQuery q1 = (BooleanQuery) standardQP.parse("someField:(foo\\-bar\\ 1\\-2\\-3)"); 
     System.out.println(q1.toString() + "  # of clauses:" + q1.getClauses().length); 
    } 
} 

上面打印:

Using org.apache.lucene.analysis.standard.StandardAnalyzer 
foo (0 3) 
bar (4 7) 
1 (8 9) 
2 (10 11) 
3 (12 13) 

Using org.apache.lucene.analysis.standard.ClassicAnalyzer 
foo (0 3) 
bar (4 7) 
1-2-3 (8 13) 

someField:foo someField:bar someField:1 someField:2 someField:3  # of clauses:5 

所以上面的代碼證明了StandardAnalyzer,不像例如ClassicAnalyzer,應該是分裂1-2-3到不同的令牌 - 這正是你想要的。對於查詢,您需要轉義每個關鍵字,包括空格,否則QP認爲這有不同的含義。

如果你不想逃避你的查詢字符串,您可以隨時手動標記化它(如上面printTokens方法),然後換用TermQuery每個標記和堆棧的所有TermQueries成BooleanQuery

+0

如果Apache文檔聲明StandardAnalyzer不會在連字符上拆分數字,爲什麼StandardAnalyzer會標記'1-2-3'? – theblang

+0

你能指出我對StandardAnalyzer的這種說法嗎?我發現StandardAnalyzer使用StandardTokenizer,它使用[Unicode Standard Annex#29](http://unicode.org/reports/tr29/)。 FWIW,我沒有深入調查過。 – mindas

+0

當然,[這是](http://lucene.apache.org/core/old_versioned_docs/versions/3_0_1/api/all/org/apache/lucene/analysis/standard/StandardTokenizer.html)。 – theblang