BooleanQuery $ TooManyClauses excepción cuando el uso de consultas comodín
-
21-09-2019 - |
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í?
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 ;)