【发布时间】:2010-07-14 23:06:40
【问题描述】:
我想在 Lucene 中将数字范围查询与术语查询结合起来。例如,我想搜索已编入索引且包含 10 到 20 页且标题为“Hello World”的文档。
似乎不可能使用 QueryParser 为我生成此查询; QueryParser 生成的范围查询似乎是文本查询。
我肯定会喜欢一个如何将数字范围查询与术语查询结合起来的示例。我也愿意采取替代搜索索引的方法。
谢谢
【问题讨论】:
我想在 Lucene 中将数字范围查询与术语查询结合起来。例如,我想搜索已编入索引且包含 10 到 20 页且标题为“Hello World”的文档。
似乎不可能使用 QueryParser 为我生成此查询; QueryParser 生成的范围查询似乎是文本查询。
我肯定会喜欢一个如何将数字范围查询与术语查询结合起来的示例。我也愿意采取替代搜索索引的方法。
谢谢
【问题讨论】:
嗯,看来这是我自己想出来的。您可以一起使用 Query.combine() 来 OR 查询。我在下面提供了一个示例。
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});
【讨论】:
您还可以创建一个自定义 QueryParser 覆盖 protected Query getRangeQuery(...) 方法,当遇到 "page_count" 字段时,它应该返回 NumericRangeQuery 实例。
就这样……
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);
}
}
然后在解析文本查询时使用CustomQueryParser..
就这样……
...
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]");
...
当然,这一切都假设在将 page_count 值添加到文档时使用了 NumericField(...).setIntValue(...)
【讨论】:
你可以使用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 将数字视为单词,因此数字按字母顺序排列。
1
12
123
1234
etc.
话虽如此,您仍然可以使用范围查询,只是需要更加聪明。
为了正确查询数值,您需要填充整数,使其长度相同(无论您支持的最大值是多少)
0001
0012
0123
1234
显然,这不适用于负数(因为 -2 http://wiki.apache.org/lucene-java/SearchNumericalFields
【讨论】: