使用Lucene:如果我进行前缀搜索,为什么会出现太多子句错误?
我有一个应用程序做了一段时间的前缀搜索。最近,索引的大小增加了,结果发现某些前缀太繁杂,以至于Lucene无法处理。它一直向我抛出"太多子句"错误,当我不断查看我的JAR并确认所包含的代码中没有一个实际上使用布尔查询时,这非常令人沮丧。
为什么它不引发" Tooth Many Hits"之类的异常呢?不会。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。当我绝对只使用前缀查询时,为什么增加布尔查询的静态max子句整数实际上会使此错误消失呢?我不了解查询的运行方式是否存在一些基本问题;是他们秘密地成为布尔查询吗?
解决方案
回答
我以前打过这与以下事实有关:在调用Query.rewrite()时,lucene在幕后将许多(全部?)内容转换为布尔查询。
来自:http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/search/Query.html#rewrite(org.apache.lucene.index.IndexReader)
public Query rewrite(IndexReader reader) throws IOException Expert: called to re-write queries into primitive queries. For example, a PrefixQuery will be rewritten into a BooleanQuery that consists of TermQuerys. Throws: IOException
回答
运行前缀查询时,Lucene会在其"词典"中搜索与查询匹配的所有术语。如果超过1024个(默认情况下)匹配,则抛出TooManyClauses-Exception。
我们可以调用BooleanQuery.setMaxClauseCount来增加每个BooleanQuery允许的最大子句数。
回答
TooManyClauses的API参考页显示,PrefixQuery,FuzzyQuery,WildcardQuery和RangeQuery以这种方式扩展(转换为BooleanQuery)。由于它在API参考中,因此它应该是用户可以依赖的行为。 Lucene不会对命中次数设置任何限制(文档ID为int除外),因此"太多命中"异常可能没有意义。也许PrefixQuery.rewrite(IndexReader)应该捕获TooManyClauses并抛出"前缀太多"异常,但是现在它的行为并不如此。
顺便说一句,按前缀搜索的另一种方法是使用PrefixFilter。或者用它过滤查询,或者用ConstantScoreQuery包裹过滤器。