【问题标题】:Combining Numeric Range Query with Term Query in LuceneLucene中结合数值范围查询和词条查询
【发布时间】:2010-07-14 23:06:40
【问题描述】:

我想在 Lucene 中将数字范围查询与术语查询结合​​起来。例如,我想搜索已编入索引且包含 10 到 20 页且标题为“Hello World”的文档。

似乎不可能使用 QueryParser 为我生成此查询; QueryParser 生成的范围查询似乎是文本查询。

我肯定会喜欢一个如何将数字范围查询与术语查询结合​​起来的示例。我也愿意采取替代搜索索引的方法。

谢谢

【问题讨论】:

    标签: java lucene


    【解决方案1】:

    嗯,看来这是我自己想出来的。您可以一起使用 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});
    

    【讨论】:

    • 你知道如何在Lucene4上实现吗?好像,Query.combine() 在 Lucene4 中不起作用
    • 嘿@Dewsworld,解决方案是使用布尔查询: BooleanQuery query = new BooleanQuery(); query.Add(new TermQuery(...), BooleanClause.Occur.MUST); query.Add(new Term.Query(...), BooleanClause.Occur.NEVER);
    【解决方案2】:

    您还可以创建一个自定义 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(...)

    【讨论】:

    • Lucene Api Javadoc 中也推荐这样做。谢谢
    【解决方案3】:

    你可以使用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);
    

    【讨论】:

      【解决方案4】:
      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-19
        • 1970-01-01
        • 1970-01-01
        • 2021-08-20
        • 2012-02-21
        相关资源
        最近更新 更多