Pergunta

Estou usando o Hibernate Search / Lucene para manter um índice realmente simples para encontrar objetos pelo nome - sem coisas sofisticadas.

Minhas aulas de modelo estendem uma aula NamedModel que parece basicamente o seguinte:

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

Meu problema é que eu recebo um BooleanQuery$TooManyClauses exceção ao consultar o índice para objetos com nomes começando com uma carta específica, por exemplo "name:l*". Uma consulta como "name:lin*" Funcionará sem problemas, de fato, qualquer consulta usando mais de uma letra antes do curinga funcionará.

Ao pesquisar na rede por problemas semelhantes, só encontrei pessoas usando consultas bastante complexas e isso sempre parecia causar a exceção. Eu não quero aumentar maxClauseCount Porque não acho que seja uma boa prática mudar de limites apenas porque você os alcança.

Qual é o problema aqui?

Foi útil?

Solução

Lucene tenta reescrever sua consulta de simples name:l* para uma consulta com todos os termos começando com L neles (algo como name:lou OR name:la OR name: ...) - Acredito que isso deve ser mais rápido.

Como solução alternativa, você pode usar um ConstantScorePrefixQuery em vez de um PrefixQuery:

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

No entanto, isso muda a pontuação dos documentos (daí a classificação se você confiar na pontuação para classificar). Enquanto enfrentamos o desafio de precisar de pontuação (e Boost), decidimos optar por uma solução onde usamos PrefixQuery Se possível e fallback para ConstantScorePrefixQuery onde necessário:

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;
    }
  }
};

(Como aprimoramento, alguém poderia usar algum tipo de LRUMap Para armazenar os termos que falharam antes de evitar passar por uma reescrita dispendiosa novamente)

Não posso ajudá -lo a integrar isso na pesquisa de hibernação. Você pode perguntar depois que mudou para Bússola ;)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top