11

在我的测试中,当我尝试从由术语查询和通配符查询组成的布尔查询中获取命中时,我突然遇到了太多子句异常。

我在网上搜索并找到了他们建议增加 BooleanQuery.SetMaxClauseCount() 的资源。
这对我来说听起来很可疑。我应该怎么做?我怎么能相信这个新的幻数足以满足我的查询?在所有地狱崩溃之前,我可以将这个数字增加多远?

总的来说,我觉得这不是一个解决方案。一定有更深层次的问题。。

查询是 +{+companyName:mercedes +paintCode:a*} 并且索引有大约 250 万个文档。

4

2 回答 2

3

查询的paintCode:a* 部分是任何以“a”开头的paintCode 的前缀查询。这就是你的目标吗?

Lucene 将前缀查询扩展为一个布尔查询,其中包含与前缀匹配的所有可能术语。在您的情况下,显然有超过 1024 个可能paintCode的以“a”开头的 s。

如果您觉得前缀查询毫无用处,那么您离事实不远了。

我建议您更改索引方案以避免使用前缀查询。我不确定您要通过示例完成什么,但是如果您想按首字母搜索油漆代码,请创建一个 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,但我不认为它更好。

于 2009-03-05T15:05:08.417 回答
0

似乎您在某种关键字类型的字段上使用它(这意味着您的数据源字段中不会有多个标记)。

这里有一个对我来说似乎很优雅的建议: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。显然,这也加快了搜索过程。

您可以轻松地自动化一个过程,该过程自动分解术语并在索引期间根据名称方案用值填充文档。

如果每个字段都有多个标记,则可能会出现一些问题。您可以在文章中找到更多详细信息

于 2011-12-14T13:48:26.607 回答