Pregunta

Estoy usando Hibernate Buscar / Lucene para mantener un índice muy simple para encontrar objetos por nombre -. Nada de extravagancias

Mis clases del modelo se extienden todos NamedModel una clase que se ve básicamente de la siguiente manera:

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

Mi problema es que tengo una excepción BooleanQuery$TooManyClauses al consultar el índice de objetos con nombres que comienzan con una letra específica, por ejemplo, "name:l*". Una consulta como "name:lin*" funcionará sin problemas, de hecho, cualquier consulta utilizando más de una letra antes del comodín va a funcionar.

Mientras que buscando en la red para problemas similares, sólo he encontrado personas que utilizan consultas muy complejas y que siempre parecía causar la excepción. No quiero aumentar maxClauseCount porque yo no creo que es una buena práctica para cambiar los límites sólo porque se llega a ellos.

¿Cuál es el problema aquí?

¿Fue útil?

Solución

Lucene intenta reescribir la consulta desde la simple name:l* a una consulta con todos los términos comenzando con l en ellos (algo así como name:lou OR name:la OR name: ...) -. Creo que esto está destinado a ser más rápido

Como solución alternativa, es posible utilizar un ConstantScorePrefixQuery en lugar de un PrefixQuery:

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

Sin embargo, esto cambia la puntuación de los documentos (de ahí la clasificación si se basan en la puntuación para la clasificación). A medida que nos enfrentamos al reto de tener puntaje (y refuerzo), decidimos ir a dar una solución en la que usamos PrefixQuery si es posible y de respaldo a ConstantScorePrefixQuery donde sea necesario:

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 mejora, se podría utilizar algún tipo de LRUMap a términos caché que falló antes para evitar ir a través de una reescritura costosa de nuevo)

No puedo ayudar con la integración de este en hibernación Búsqueda sin embargo. Usted puede preguntar después de que haya cambiado a Brújula ;)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top