在我的测试中,当我试图从一个由termquery和一个通配符查询组成的布尔查询中获取命中时,我突然遇到了Too Many Clauses异常。
我在网上搜索并找到他们建议增加BooleanQuery.SetMaxClauseCount()的资源。
这对我来说听起来很可疑..我该怎么办呢?我如何能够依赖这个新的幻数足以满足我的查询?在所有地狱破裂之前我能在多长时间内增加这个数字?
总的来说,我觉得这不是解决方案。必须有更深层次的问题..
查询是+ {+ companyName:mercedes + paintCode:a *},索引有~2.5万个文档。
答案 0 :(得分:3)
paintCode:查询的* *部分是以“a”开头的任何paintCode的前缀查询。那是你的目标吗?
Lucene将前缀查询扩展为包含与前缀匹配的所有可能术语的布尔查询。在您的情况下,显然有超过1024个可能以“a”开头的paintCode
。
如果听起来像前缀查询是没用的,那么你离事实并不远。
我建议您更改索引方案以避免使用前缀查询。我不确定你要用你的例子做什么,但是如果你想用第一个字母搜索绘画代码,请创建一个paintCodeFirstLetter字段并按该字段搜索。
如果您非常绝望,并且愿意接受部分结果,您可以从源代码构建自己的Lucene版本。您需要对PrefixQuery.java
下的文件MultiTermQuery.java
和org/apache/lucene/search
进行更改。在两个类的rewrite
方法中,更改行
query.add(tq, BooleanClause.Occur.SHOULD); // add to query
到
try {
query.add(tq, BooleanClause.Occur.SHOULD); // add to query
} catch (TooManyClauses e) {
break;
}
我为自己的项目做了这件事并且有效。
如果你真的不喜欢改变Lucene的想法,你可以编写自己的PrefixQuery变体和自己的QueryParser,但我认为它不会更好。
答案 1 :(得分:0)
您好像在一个 Keyword 类型的字段上使用它(意味着您的数据源字段中不会有多个令牌)。
这里有一个建议对我来说似乎很优雅:http://grokbase.com/t/lucene.apache.org/java-user/2007/11/substring-indexing-to-avoid-toomanyclauses-exception/12f7s7kzp2emktbn66tdmfpcxfya
基本思路是将您的术语分解为多个字段,并增加长度,直到您确定不会达到子句限制为止。
示例:强>
想象一下像这样的paintCode:
"a4c2d3"
索引此值时,可在文档中创建以下字段值:
[paintCode]: "a4c2d3"
[paintCode1n]: "a"
[paintCode2n]: "a4"
[paintCode3n]: "a4c"
当您查询时,您的术语中的字符数决定了要搜索的字段。这意味着您将对多于3个字符的术语执行前缀查询 ,这会大大减少内部结果计数,从而防止臭名昭着的 TooManyBooleanClausesException 。显然,这也加快了搜索过程。
您可以轻松地自动执行自动分解条款的流程,并在编制索引期间根据名称方案使用值填充文档。
如果每个字段都有多个令牌,则可能会出现一些问题。您可以在文章中找到更多详细信息