2008-11-04 13 views
29

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.¿Cómo hacer que Lucene QueryParser sea más indulgente?

Estoy seguro de que otras personas han abordado este problema, 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 prevenir ParseExceptions al procesar consultas de los usuarios? Me parece que la interfaz de búsqueda más utilizable es una que siempre ejecuta una consulta, incluso si puede ser una consulta incorrecta.

Parece que hay algunas estrategias posibles y complementarios,:

  • "limpia" la consulta antes de enviarla a los QueryProcessor
  • excepciones controlar correctamente
    • muestran un inteligente mensaje de error al usuario
    • Quizás ejecute una consulta más simple, dejando fuera del bit erróneo

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

Respuesta

1

Estoy en la misma situación que usted.

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 Lucene que he simplificado un poco:
http://ifdefined.com/btnet/lucene_syntax.html

8

Bueno, la cosa más fácil de hacer sería dar la forma cruda de la consulta de un tiro , y si eso falla, vuelva a limpiarlo.

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 da la forma cruda de la consulta del usuario la oportunidad de correr, pero si falla el análisis sintáctico, que tira de todo, excepto letras, números, espacios y guiones; entonces intentamos de nuevo. Aún corremos el riesgo de lanzar ParseException, pero hemos reducido drásticamente las probabilidades.

También podría considerar tokenizar la consulta del usuario usted mismo, 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

1

No sé mucho sobre Lucene.net. Para Lucene en general, recomiendo el libro Lucene in Action. 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.

42

Yo puede hacer caso omiso de Lucene los caracteres especiales desinfectando la consulta con algo como

query = QueryParser.Escape(query) 

Si no desea que sus usuarios utilizan cada vez sintaxis avanzada en sus consultas, puede hacerlo siempre.

Si desea que sus usuarios usen una 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.

+0

tuve el problema ParseException y utilicé esta solución porque mis usuarios no utilizarán la sintaxis avanzada. Gracias ! – Costo

1

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

3

FYI ... Aquí está el código que estoy utilizando 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\[email protected]]", " "); 
      q = qp.Parse(cooked); 
     } 

     return q; 
    } 
+0

Esta respuesta básicamente copió una respuesta anterior. –

+0

@ james.garriss Sé que este hilo ha muerto hace mucho tiempo, pero tuve que decirlo. Aunque puede que tenga razón, pero me ayudó a asegurarme de que funcionará como se espera en C# también. Además, el Regex en esta respuesta es más completo. :) –

Cuestiones relacionadas