使用通配符查询时,BooleanQuery $ TooManyClauses异常

时间:2009-10-15 07:59:41

标签: java exception hibernate-search

我正在使用Hibernate Search / Lucene维护一个非常简单的索引来按名称查找对象 - 没有花哨的东西。

我的模型类都扩展了一个类NamedModel,它看起来基本如下:

@MappedSuperclass
public abstract class NamedModel {
    @Column(unique = true)
    @Field(store = Store.YES, index = Index.UN_TOKENIZED)
    protected String name;
}

我的问题是,当查询名称以特定字母开头的对象的索引时,我得到BooleanQuery$TooManyClauses异常,例如"name:l*"。 像"name:lin*"之类的查询可以正常运行,实际上在通配符之前使用多个字母的任何查询都可以正常工作。

在网上搜索类似的问题时,我发现人们只使用非常复杂的查询,但似乎总是会导致异常。我不想增加maxClauseCount,因为我不认为改变限制只是因为你达到它们是一个好习惯。

这里有什么问题?

1 个答案:

答案 0 :(得分:3)

Lucene尝试将您的查询从简单的name:l*重写为一个查询,其中包含所有以l开头的术语(类似name:lou OR name:la OR name: ...) - 我相信这意味着更快。

作为解决方法,您可以使用ConstantScorePrefixQuery代替PrefixQuery

// instead of new PrefixQuery(prefix)
new ConstantScoreQuery(new PrefixFilter(prefix));

但是,这会改变文档的评分(因此,如果您依赖分数进行排序,则会进行排序)。当我们面临需要得分(和提升)的挑战时,我们决定寻求一个解决方案,如果可能的话我们会使用PrefixQuery并在需要时回退到ConstantScorePrefixQuery

new PrefixQuery(prefix) {
  public Query rewrite(final IndexReader reader) throws IOException {
    try {
      return super.rewrite(reader);
    } catch (final TooManyClauses e) {
      log.debug("falling back to ConstantScoreQuery for prefix " + prefix + " (" + e + ")");
      final Query q = new ConstantScoreQuery(new PrefixFilter(prefix));
      q.setBoost(getBoost());
      return q;
    }
  }
};

(作为一项增强功能,可以使用某种LRUMap来缓存之前失败的术语,以避免再次进行代价高昂的重写。

我无法帮助您将其集成到Hibernate Search中。在您切换到Compass;)

后,您可能会问