Pregunta

En mis pruebas, de repente me topé con una excepción de demasiadas cláusulas al intentar obtener los resultados de una consulta booleana que consistía en una consulta de término y una consulta comodín.

Busqué en la red y en los recursos encontrados sugieren que aumente BooleanQuery.SetMaxClauseCount ().
Esto me suena a pescado ... ¿A qué debo subir? ¿Cómo puedo confiar en que este nuevo número mágico será suficiente para mi consulta? ¿Hasta qué punto puedo incrementar este número antes de que se desate todo el infierno?

En general siento que esto no es una solución. Debe haber un problema más profundo ...

La consulta fue + {+ companyName: mercedes + paintCode: a *} y el índice tiene ~ 2.5 millones de documentos.

¿Fue útil?

Solución

el paintCode: a * parte de la consulta es una consulta de prefijo para cualquier paintCode que comienza con un " a " ¿Es eso lo que estás buscando?

Lucene expande las consultas de prefijo en una consulta booleana que contiene todos los términos posibles que coinciden con el prefijo. En su caso, al parecer hay más de 1024 posibles paintCode que comienzan con un " a " ;.

Si le parece que las consultas de prefijo son inútiles, no está muy lejos de la verdad.

Le sugiero que cambie su esquema de indexación para evitar el uso de una consulta de prefijo. No estoy seguro de lo que está tratando de lograr con su ejemplo, pero si desea buscar códigos de pintura por primera letra, cree un campo paintCodeFirstLetter y busque por ese campo.

AÑADIDO

Si está desesperado y está dispuesto a aceptar resultados parciales, puede crear su propia versión de Lucene desde la fuente. Debe realizar cambios en los archivos PrefixQuery.java y MultiTermQuery.java , ambos en org / apache / lucene / search . En el método rewrite de ambas clases, cambie la línea

query.add(tq, BooleanClause.Occur.SHOULD);          // add to query

a

try {
    query.add(tq, BooleanClause.Occur.SHOULD);          // add to query
} catch (TooManyClauses e) {
    break;
}

Hice esto para mi propio proyecto y funciona.

Si realmente no le gusta la idea de cambiar Lucene, podría escribir su propia variante PrefixQuery y su propio QueryParser, pero no creo que sea mucho mejor.

Otros consejos

Parece que está utilizando esto en un campo que es una especie de palabra clave (lo que significa que no habrá múltiples tokens en su campo de origen de datos).

Aquí hay una sugerencia que me parece bastante elegante: http://grokbase.com/t/lucene.apache.org/java-user/2007/11/substring-indexing-to-avoid-toomanyclauses-exception/ 12f7s7kzp2emktbn66tdmfpcxfya

La idea básica es dividir su término en múltiples campos con una longitud creciente hasta que esté bastante seguro de que no alcanzará el límite de la cláusula.

Ejemplo :

Imagine un código de pintura como este:

"a4c2d3"

Al indexar este valor, crea los siguientes valores de campo en su documento:

[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"

En el momento de la consulta, el número de caracteres en su término decide en qué campo buscar. Esto significa que realizará una consulta de prefijo solo para términos con más de 3 caracteres, lo que disminuye en gran medida el recuento interno de resultados, evitando la infame TooManyBooleanClausesException . Aparentemente, esto también acelera el proceso de búsqueda.

Puede automatizar fácilmente un proceso que desglosa los términos automáticamente y llena los documentos con valores de acuerdo con un esquema de nombre durante la indexación.

Pueden surgir algunos problemas si tiene múltiples tokens para cada campo. Puedes encontrar más detalles en el artículo

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