jueves, 15 de septiembre de 2011

Lucene: sin regla ni Compass

Saludos después de una larga pausa donde, básicamente, me he dedicado a la familia y al ocio, para que negarlo. La verdad es que no estaba seguro de si volvería a escribir o no en el blog, ya que mi visión de eso llamado comunidad se va degradando con el tiempo, pero los ánimos me han dado para algunas entradas más, y aquí estamos de nuevo.

Esta entrada debería haber sido algo diferente, ya que mi intención era principalmente comentar la librería Compass, que es una especie de envoltorio de Lucene para facilitar su uso cuando tratamos con objetos Java, pero después de usarla en unos cuantos proyectos y estar relativamente satisfecho con su uso, un ligero problemilla me hizo consultar sus listas de distribución donde buceando entre el spam me encontré con la sorpresa de que su autor declaraba oficialmente que pasaba a hacer otra cosa y que ya no le interesaba trabajar en la librería. Al ser un one-man project, la cosa queda en que Compass es, en estos momentos, “abandonware”, por lo que hacer entradas explicando su uso, ventajas… me parece hacerle un flaco favor al pobre programador que debido a ellas acabe usándola y encontrándose la misma desagradable sorpresa que yo.
Sin embargo, aparte de advertir del estado del Compass, he decido modificar el contenido de la entrada y limitarme a hablar de los conceptos que he aprendido últimamente del Lucene y que son aplicables fuera de Compass.

Así que si alguna vez te toca trabajar con Lucene, espero que estos consejillos te sirvan:
  • Lo más normal, si estas realizando búsquedas en castellano o algún lenguaje con caracteres "raros" para los anglos, es que quieras usar un analizador personalizado (custom analyzer) que utilice, al menos, los filtros ISOLatin1AccentFilter, LowerCaseFilter y StandardFilter. De esta forma tus documentos (así es como llama Lucene a lo que sea que indexes) se indexarán sin tener en cuenta mayúsculas, ni acentos u otros caracteres no-ascii.
  • Eso sí, una vez indexados los documentos de esa forma, ojo con una característica del Lucene muy desagradable: Las búsquedas se deben pasar, habitualmente, por el mismo analizador que al indexar, pero el Lucene ignora al analizador sin decir nada si en las búsquedas se usan comodines (‘*’ o ‘?’). Así que si realizamos una búsqueda sin comodines, los resultados no serán independientes de las mayúsculas o los acentos y nos llevaremos desagradables sorpresas. La excusa oficial, con su pequeña parte lógica, es que el analizador puede cambiar los términos de búsqueda, por ejemplo para buscar  en singular y plural indistintamente, y entonces al hacer esos cambios junto a comodines, el termino final de búsqueda podría no parecerse a lo que quería el usuario. Bueno, vale. ¡Pero déjame elegir! En nuestro caso no puede ocurrir nada de eso, simplemente cambiamos letras mayúsculas por minúsculas y cambiamos á por a … pero Lucene considera que dejar escoger al programador, pobre tonto, es un peligro y no da la opción de desactivar esa “ayudita”. Sin comentarios. La única solución que he encontrado es pasar por esos mismo filtros los términos de búsqueda “manualmente” y antes de pasárselos al Lucene, lo cual me parece una chapuza. Pero avisados quedáis.
  • Otro truco útil es para cuando la gente quiere hacer una búsqueda de palabras que “acaben en”, o sea *algo . Lucene está pensado para búsquedas que “empiecen por”, o sea algo*, y en cambio empezar por un comodín es muy ineficiente. ¿Como solventarlo? Muy sencillo, a la hora de indexar, indexamos ese campo al revés y a la hora de buscar le damos la vuelta al termino de búsqueda, o sea ogla*. Por el módico precio de tener indexado el campo dos veces, volvemos a tener búsquedas eficientes: voilà.
  • Este último caso es un claro ejemplo de una técnica general muy útil cuando trabajamos con búsquedas indexadas, lo que hacemos con Lucene, vaya: En caso de tener problemas al montar el criterio de búsqueda, se puede probar a modificar la forma en que se indexa el contenido para facilitar las cosas. Por ejemplo, tenemos una lista de productos que pueden venderse en distintas tiendas y de esas tiendas hay sucursales en distintas provincias. Si a la hora de indexar, usamos un campo para indexar la lista de tiendas en las que se vende un producto y en otro campo la lista de provincias donde se vende… ¿Cómo podemos saber en qué provincias se vende el producto X en una tienda determinada? La respuesta es que así indexado no lo podemos saber, ya que hemos perdido la relación tienda-provincia. En este caso lo que tenemos que hacer es crear un nuevo campo donde indexemos el par tienda-provincia, que es por el que buscaremos para este tipo de consultas.
  • De igual forma, podemos indexar en varios campos los apellidos junto con el nombre o los apellidos por separado, según como queramos poder buscarlos. A no ser que tengamos un índice de modificaciones muy alto, o un volumen de datos inmenso, no hay que tener miedo en invertir en la indexación a cambio de obtener un rendimiento mucho más alto en la parte presumiblemente más usada: las búsquedas.

Happy coding! EJ

No hay comentarios:

Publicar un comentario