3

私はHibernateSearch/ 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

name:l*Lucene は、単純なクエリから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に切り替えた後に尋ねるかもしれません;)

于 2009-10-15T08:39:28.053 に答える