Reputation: 5351
I'm indexing some items which include title
and cost
as fields. Cost is a double value.
I'm preparing a query such as:
(title:item~0.8) AND (cost:[0.0 TO 200.0])
After parsing, query.toString()
looks like this:
+title:item~0 +cost:[0.0 TO 200.0]
From the results returned, it is obvious that cost
is not considered.
I know for sure that cost
is indexed because I can retrieve it.
Indexing code:
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");
}
Upvotes: 1
Views: 5607
Reputation: 5351
I ended up subclassing QueryParser
and then creating a NumericRange
when cost
is encountered. It works well.
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);
}
}
And then initialize:
QueryParser queryParser = new WebSearchQueryParser("title", new StandardAnalyzer());
and parse my query as before (title:item~0.8) AND (cost:[0.0 TO 200.0])
Upvotes: 3
Reputation: 33351
QueryParser
does not generate numeric range queries. So you are searching for values where cost is between 0.0 and 200.0 lexicographically, rather than numerically. Furthermore, numeric fields are translated to a prefix coded form in the index, so your results will be pretty unpredictable.
It's better to generate your numeric ranges through the Query API, using NumericRangeQuery
, instead of the QueryParser, and them combine them with your parsed query using a BooleanQuery
. Something like:
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));
Upvotes: 2