2015-01-04 56 views
0

我正在索引一些項目,其中包括titlecost作爲字段。成本是雙重價值。 我準備的查詢,如:帶範圍的Lucene查詢

(title:item~0.8) AND (cost:[0.0 TO 200.0]) 

解析後,query.toString()看起來是這樣的:

+title:item~0 +cost:[0.0 TO 200.0] 

從返回的結果,很明顯,cost不考慮。 我知道cost被索引,因爲我可以檢索它。 索引代碼:

public void index(Set<Item> items) throws IOException { 
    String path = "D:\\lucenedata\\myproj"; 
    Directory fsDir = FSDirectory.open(new File(path)); 
    StandardAnalyzer analyzer = new StandardAnalyzer(); 
    IndexWriterConfig iwConf = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); 
    iwConf.setOpenMode(IndexWriterConfig.OpenMode.CREATE); 
    IndexWriter indexWriter = new IndexWriter(fsDir, iwConf); 
    for (Item item : items) { 
     Document d = new Document(); 
     if (item.getCost() != null) { 
      d.add(new DoubleField("cost", item.getCost().doubleValue(), Store.YES)); 
     } 
     d.add(new TextField("title", item.getTitle(), Store.YES)); 
     indexWriter.addDocument(d); 
    } 
    indexWriter.commit(); 
    indexWriter.close(); 
    System.out.println("Indexed " + items.size() + " items"); 
} 

回答

2

我結束了繼承QueryParser然後創建一個NumericRange遇到cost時。它運作良好。

public class WebSearchQueryParser extends QueryParser { 

    public WebSearchQueryParser(String f, Analyzer a) { 
     super(f, a); 
    } 

    protected Query getRangeQuery(final String field, final String min, final String max, 
      final boolean startInclusive, final boolean endInclusive) throws ParseException { 
     if ("cost".equals(field)) { 
      return NumericRangeQuery.newDoubleRange(field, Double.parseDouble(min), Double.parseDouble(max), 
        startInclusive, endInclusive); 
     } 
     return super.getRangeQuery(field, min, max, startInclusive, endInclusive); 
    } 
} 

然後初始化:

QueryParser queryParser = new WebSearchQueryParser("title", new StandardAnalyzer()); 

和解析我查詢作爲前(title:item~0.8) AND (cost:[0.0 TO 200.0])

1

QueryParser不會產生數字範圍查詢。所以你正在尋找價值在0.0到200.0之間的數值,而不是數字。此外,數字字段在索引中被轉換爲前綴編碼形式,所以你的結果將是不可預測的。

最好通過查詢API生成數字範圍,使用NumericRangeQuery而不是QueryParser,然後用BooleanQuery將它們與解析後的查詢結合起來。喜歡的東西:

Query parsedQuery = parser.parse(title:item~0.8); 
Query costQuery = NumericRangeQuery.newDoubleRange("cost", 0.00, 200.0, true, true); 
BooleanQuery finalQuery = new BooleanQuery(); 
finalQuery.add(new BooleanClause(parsedQuery, BooleanClause.Occur.MUST)); 
finalQuery.add(new BooleanClause(costQuery, BooleanClause.Occur.MUST)); 
+0

感謝您的解釋。我還發現,這種方式並不適用。相反,我寫了一個自定義的QueryParser,如果遇到「cost」列,它將創建新的NumericRange。我也會發布我的解決方案。 – isah 2015-01-05 13:03:22