sintaxis query parser lucene lucene.net

sintaxis - ¿Cómo hacer que el Lucene QueryParser sea más indulgente?



lucene query parser syntax (6)

Bueno, lo más fácil sería dar un solo paso a la consulta de la consulta, y si eso falla, vuelva a limpiarla.

Query safe_query_parser(QueryParser qp, String raw_query) throws ParseException { Query q; try { q = qp.parse(raw_query); } catch(ParseException e) { q = null; } if(q==null) { String cooked; // consider changing this "" to " " cooked = raw_query.replaceAll("[^/w/s]",""); q = qp.parse(cooked); } return q; }

Esto le da la oportunidad a la forma cruda de la consulta del usuario de ejecutarse, pero si el análisis falla, lo despojamos de todo, excepto letras, números, espacios y guiones bajos; entonces intentamos de nuevo. Aún corremos el riesgo de lanzar ParseException, pero hemos reducido drásticamente las probabilidades.

También podría considerar convertir en token la consulta del usuario, convirtiendo cada token en una consulta de término y englobándolos junto con una BooleanQuery. Si realmente no espera que sus usuarios aprovechen las características de QueryParser, esa sería la mejor opción. Sería completamente (?) Robusto y los usuarios podrían buscar cualquier personaje divertido que lo haga a través de su analizador.

Estoy usando Lucene.net, pero estoy etiquetando esta pregunta para ambas versiones .NET y Java porque la API es la misma y espero que haya soluciones en ambas plataformas.

Estoy seguro de que otras personas abordaron este tema, pero no he podido encontrar buenas discusiones o ejemplos.

Por defecto, Lucene es muy exigente con la sintaxis de las consultas. Por ejemplo, acabo de recibir el siguiente error:

[ParseException: Cannot parse ''hi there!'': Encountered "<EOF>" at line 1, column 9. Was expecting one of: "(" ... "*" ... <QUOTED> ... <TERM> ... <PREFIXTERM> ... <WILDTERM> ... "[" ... "{" ... <NUMBER> ... ] Lucene.Net.QueryParsers.QueryParser.Parse(String query) +239

¿Cuál es la mejor manera de evitar ParseExceptions al procesar consultas de los usuarios? Me parece que la interfaz de búsqueda más útil es aquella que siempre ejecuta una consulta, incluso si es una consulta incorrecta.

Parece que hay algunas estrategias posibles y complementarias:

  • "Limpiar" la consulta antes de enviarla al QueryProcessor
  • Maneje las excepciones con gracia
    • Mostrar un mensaje de error inteligente para el usuario
    • Tal vez ejecutar una consulta más simple, dejando fuera el bit erróneo

Realmente no tengo grandes ideas sobre cómo hacer ninguna de esas estrategias. ¿Alguien más ha abordado este problema? ¿Hay analizadores "simples" o "graciosos" que no conozca?


Estoy en la misma situación que tú.

Esto es lo que hago. Capté la excepción, pero solo para que el error parezca más bonito. No cambio el texto

También proporciono un enlace a una explicación de la sintaxis de Lucene que he simplificado un poco:
http://ifdefined.com/btnet/lucene_syntax.html


No sé mucho sobre Lucene.net. Para el general Lucene, recomiendo mucho el libro Lucene en acción . Para la pregunta en cuestión, depende de tus usuarios. Existen razones importantes, como la facilidad de uso, la seguridad y el rendimiento, para limitar las consultas de los usuarios. El libro muestra formas de analizar las consultas utilizando un analizador personalizado en lugar de QueryParser. Apoyo la idea de Jay sobre BooleanQuery, aunque puedes construir consultas más fuertes usando un analizador personalizado.


Puedes hacer que Lucene ignore los caracteres especiales desinfectando la consulta con algo así como

query = QueryParser.Escape(query)

Si no desea que sus usuarios usen nunca la sintaxis avanzada en sus consultas, puede hacerlo siempre.

Si desea que sus usuarios usen sintaxis avanzada pero también desea ser más tolerante con los errores, solo debe desinfectarse después de que se haya producido una excepción ParseException.


Si no necesita todas las funciones de Lucene, puede mejorar escribiendo su propio analizador de consultas. No es tan complicado como podría parecer en primer lugar.


FYI ... Aquí está el código que estoy usando para .NET

private Query GetSafeQuery(QueryParser qp, String query) { Query q; try { q = qp.Parse(query); } catch(Lucene.Net.QueryParsers.ParseException e) { q = null; } if(q==null) { string cooked; cooked = Regex.Replace(query, @"[^/w/.@-]", " "); q = qp.Parse(cooked); } return q; }