12

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.

Thanks

4 Answers 4

11

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}); 
Sign up to request clarification or add additional context in comments.

2 Comments

Do you know how to implement it on Lucene4? Seems like, Query.combine() is not working in Lucene4
Hey @Dewsworld, the solution is to use a Boolean Query: BooleanQuery query = new BooleanQuery(); query.Add(new TermQuery(...), BooleanClause.Occur.MUST); query.Add(new Term.Query(...), BooleanClause.Occur.NEVER);
5

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

1 Comment

This is also recommended in the Lucene Api Javadoc. Thanks
2

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); 

Comments

0
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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.