Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make the QueryParser in Lucene handle numeric ranges?

Tags:

java

lucene

new QueryParser(.... ).parse (somequery);

it works only for string indexed fields. Say i have a field called count where count is a integer field (while indexing the field I considered the data type)

new QueryParser(....).parse("count:[1 TO 10]");

The above one is not works. Instead If i used "NumericRangeQuery.newIntRange" which is working. But, i need the above one only...

like image 950
Nageswaran Avatar asked Feb 17 '11 07:02

Nageswaran


1 Answers

Had the same issue and solved it, so here I share my solution:

To create a custom query parser that will parse the following query "INTFIELD_NAME:1203" or "INTFIELD_NAME:[1 TO 10]" and handle the field INTFIELD_NAME as an Intfield, I overrided newTermQuery with the following:

public class CustomQueryParser extends QueryParser {

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

protected Query newRangeQuery(String field, String part1, String part2, boolean startInclusive,
    boolean endInclusive) {

    if (INTFIELD_NAME.equals(field)) {
    return NumericRangeQuery.newIntRange(field, Integer.parseInt(part1), Integer.parseInt(part2),
        startInclusive, endInclusive);
    }
    return (TermRangeQuery) super.newRangeQuery(field, part1, part2, startInclusive, endInclusive);
}


protected Query newTermQuery(Term term) {
    if (INTFIELD_NAME.equals(term.field())) {

    BytesRefBuilder byteRefBuilder = new BytesRefBuilder();
    NumericUtils.intToPrefixCoded(Integer.parseInt(term.text()), 0, byteRefBuilder);
    TermQuery tq = new TermQuery(new Term(term.field(), byteRefBuilder.get()));

    return tq;
    } 
    return super.newTermQuery(term);

}
}

I took the code quoted in that thread from http://www.mail-archive.com/[email protected]&q=subject:%22Re%3A+How+do+you+properly+use+NumericField%22&o=newest&f=1 and made 3 modifications :

  • rewrote newRangeQuery a little more nicely

  • replaced in newTermQuery method NumericUtils.intToPrefixCoded(Integer.parseInt(term.text()),NumericUtils.PRECISION_STEP_DEFAULT)));

    by NumericUtils.intToPrefixCoded(Integer.parseInt(term.text()), 0, byteRefBuilder);

when I used this method for the first time in a filter on the same numeric field, I put 0 as I found it as a default value in a lucene class and it just worked.

  • replaced on newTermQuery

    TermQuery tq = new TermQuery(new Term(field,

by TermQuery tq = new TermQuery(new Term(term.field(),

using "field" is wrong, because if your query has several clauses (FIELD:text OR INTFIELD:100), it is taking the first or previous clause field.

like image 155
Jeremie Avatar answered Sep 23 '22 14:09

Jeremie