【问题标题】:BooleanQuery$TooManyClauses exception when using wildcard queries使用通配符查询时出现 BooleanQuery$TooManyClauses 异常
【发布时间】:2009-10-15 07:59:41
【问题描述】:

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

这里有什么问题?

【问题讨论】:

    标签: java exception hibernate-search


    【解决方案1】:

    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 后你可能会问 ;)

    【讨论】:

    • 非常感谢。据我所知,没有直接的方法可以更改为 Hibernate Search 生成的 Query 类型。但我将使用的分析器更改为KeywordAnalyer,它不会生成失效的查询,也更适合我的需求。
    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 2021-04-04
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    相关资源
    最近更新 更多