开发者

Combining Numeric Range Query with Term Query in Lucene

开发者 https://www.devze.com 2023-01-07 00:29 出处:网络
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 \"Hel

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

0

精彩评论

暂无评论...
验证码 换一张
取 消