I would like to combine a numeric range query with a term query in Lucene. For example, I want to search for documents that I have indexed that contain between 10 and 20 pages and have the title "Hello World".
It does not seem possibly to use the QueryParser to generate this query for me; the range query that the QueryParser generates appears to be a text one.
I definitely would appreciate an example of how to combine a numeric range query with a term query. I would also be open taking an alternative to searching my index.
T开发者_开发技巧hanks
Well it looks like I figured this one out on my own. You can use Query.combine() to OR queries together. I have included an example below.
String termQueryString = "title:\"hello world\"";
Query termQuery = parser.parse(termQueryString);
Query pageQueryRange = NumericRangeQuery.newIntRange("page_count", 10, 20, true, true);
Query query = termQuery.combine(new Query[]{termQuery, pageQueryRange});
You can also create a custom QueryParser overriding protected Query getRangeQuery(...)
method, which should return NumericRangeQuery
instance when "page_count"
field is encountered.
Like so...
public class CustomQueryParser extends QueryParser {
public CustomQueryParser(Version matchVersion, String f, Analyzer a) {
super(matchVersion, f, a);
}
@Override
protected Query getRangeQuery(final String field, final String part1, final String part2, final boolean inclusive) throws ParseException {
if ("page_count".equals(field)) {
return NumericRangeQuery.newIntRange(field, Integer.parseInt(part1), Integer.parseInt(part2), inclusive, inclusive);
}
// return default
return super.getRangeQuery(field, part1, part2, inclusive);
}
}
Then use CustomQueryParser
when parsing textual queries..
Like so...
...
final QueryParser parser = new CustomQueryParser(Version.LUCENE_35, "some_default_field", new StandardAnalyzer(Version.LUCENE_35));
final Query q = parser.parse("title:\"hello world\" AND page_count:[10 TO 20]");
...
This all, of course, assumes that NumericField(...).setIntValue(...)
was used when page_count
values were added to documents
You may use BooleanQuery
:
var combinedQuery = new BooleanQuery();
combinedQuery.Add(new TermQuery(new Term("title","hello world")),Occur.MUST);
combinedQuery.Add(NumericRangeQuery.newIntRange("page_count", 10, 20, true, true),Occur.MUST);
RangeQuery amountQuery = new RangeQuery(lowerTerm, upperTerm, true);
Lucene treats numbers as words, so the numbers are ordered alphabetically.
1
12
123
1234
etc.
That being said, you can still use the range query, you just need to be more clever about it.
In order to query numeric values correctly, you need to pad your integers so the same lengths (whatever your maximum supported value is)
0001
0012
0123
1234
Obviously, this doesn't work for negative numbers (since -2 < -1), and hopefully you won't have to deal with them. Here's a useful article for negatives if you do encounter them: http://wiki.apache.org/lucene-java/SearchNumericalFields
精彩评论