3

我正在使用 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,因为我认为仅仅因为达到限制就改变限制不是一个好习惯。

这里有什么问题?

4

1 回答 1

3

Lucene 尝试将您的查询从简单name:l*的查询重写为所有以 l 开头的术语的查询(类似于name:lou OR name:la OR name: ...) - 我相信这是为了更快。

作为一种解决方法,您可以使用 aConstantScorePrefixQuery而不是 a PrefixQuery

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

但是,这会改变文档的评分(因此,如果您依赖 score 进行排序,则会进行排序)。当我们面临需要得分(和提升)的挑战时,我们决定寻找一个解决方案,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后,您可能会问;)

于 2009-10-15T08:39:28.053 回答