防止;“条款太多”;关于lucene查询

防止;“条款太多”;关于lucene查询,lucene,Lucene,在我的测试中,当我试图从一个由termquery和通配符查询组成的布尔查询中获取命中率时,突然遇到了一个过多子句异常 我在网上搜索,找到了他们建议增加BooleanQuery.SetMaxClauseCount()的资源。 这听起来很可疑。。我该怎么做呢?我怎么能相信这个新的幻数足以满足我的查询?在所有的麻烦都爆发之前,我能把这个数字增加多少 总的来说,我觉得这不是一个解决办法。一定有更深层次的问题 查询是+{+companyName:mercedes+paintCode:a*},索引有大约25

在我的测试中,当我试图从一个由termquery和通配符查询组成的布尔查询中获取命中率时,突然遇到了一个过多子句异常

我在网上搜索,找到了他们建议增加BooleanQuery.SetMaxClauseCount()的资源。
这听起来很可疑。。我该怎么做呢?我怎么能相信这个新的幻数足以满足我的查询?在所有的麻烦都爆发之前,我能把这个数字增加多少

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


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

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

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

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

我建议您更改索引方案,以避免使用前缀查询。我不确定您试图通过示例实现什么,但如果您想按第一个字母搜索绘制代码,请创建一个paintCodeFirstLetter字段并按该字段搜索

补充 如果您感到绝望,并且愿意接受部分结果,您可以从源代码构建自己的Lucene版本。您需要更改
org/apache/lucene/search
下的文件
PrefixQuery.java
MultiTermQuery.java
。在两个类的
rewrite
方法中,更改行

query.add(tq, BooleanClause.Occur.SHOULD);          // add to query

我这样做是为了我自己的项目,它的工作


如果你真的不喜欢改变Lucene的想法,你可以编写你自己的PrefixQuery变体和你自己的QueryParser,但我不认为这更好。

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

这里有一个建议在我看来相当优雅:

基本思想是将术语分解为多个字段,并增加长度,直到您确信不会达到子句限制为止

示例:

想象一下这样的代码:

"a4c2d3"
为该值编制索引时,可以在文档中创建以下字段值:

[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"
在查询时,术语中的字符数决定了搜索哪个字段。这意味着您将只对包含3个以上字符的术语执行前缀查询,这将大大减少内部结果计数,从而防止臭名昭著的TooManyBooleanClausesException。显然,这也加快了搜索过程

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


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

它是自动完成下拉列表的后端。难道没有办法让它只返回已经找到的结果吗?嗯,所以没有默认选项。。这有点让人沮丧。感谢您的回复。对于自动完成字段,为什么不使用从索引读取器返回的术语枚举并维护您自己的缓存列表?你需要时不时地检查索引阅读器来刷新列表,但至少你会有完全的灵活性…嗯,事实上,这不是一个坏主意。。在Lucene和我自己的过滤上分配我的搜索有点愚蠢,但这是我现在能想到的最好的事情。
[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"