在Lucene中替换领先的通配符查询

时间:2018-12-03 23:54:00

标签: java lucene

我有一个应用程序,该应用程序在索引中搜索具有未知前缀的匹配条形码,该条形码可能存在也可能不存在。当前,应用程序在 WildcardQuery 中使用前导通配符来说明前缀,但是,这显然会导致性能问题。我已经研究过使用ReverseStringFilter,但是它使用了TokenStream,并且不确定在这种情况下如何使用它。

这是当前实现方式的一个非常基本的示例,但是应该让您对正在发生的事情有一个很好的了解:

BooleanQuery allBCQueries;
BooleanQuery bcQuery;
for( barcode : barcodeList){
  bcQuery.add( new WildcardQuery( new Term('barcode', "*" + barcode)), Occur.Must);
  allBCQueries.add(bcQuery, Occur.should);
}
BooleanQuery result;
result.add(allBCQueries, Occur.Must);

然后将结果用于搜索索引。

有没有一种方法可以消除领先的通配符以提高性能?

1 个答案:

答案 0 :(得分:0)

正如我在评论中所述-想法是使用ReverseStringFilter,它可以有效地还原令牌,而不是条形码“ 123123”会创建令牌“ 321321”。这意味着那些带有意外前缀的查询可以被重写。

我们可以使用查询barcode:*123代替barcode:123*,它会更加有效。

添加带有自定义TokenStream的文档非常简单:

final Tokenizer token = new KeywordTokenizer();
Document doc = new Document();
token.setReader(new StringReader(value));
doc.add(new TextField("barcode", value, Field.Store.YES));
doc.add(new TextField("reverse-barcode", new ReverseStringFilter(token)));

这样,我们在保留原始值的同时应用了关键字标记器(例如,没有标记器)+反向字符串过滤器

我已经对100万个填充有随机条形码的文档进行了一些测试(例如,我的情况是长整型),反向方法大约带来了 30%的优势,同时提供的结果数量完全相同。 / p>

可以找到完整的示例there