viernes, 9 de agosto de 2013

Búsquedas de texto completo en objetos de dominio

Hibernate
Si hace un tiempo hablaba de un problema muy común que nos encontramos al desarrollar una aplicación como los es internacionalizar los textos de algunos campos de una entidad de dominio, el hacer búsquedas de texto completo sobre esos campos más allá del like que nos ofrece el lenguaje SQL de las base de datos también es un problema a resolver.

La primera solución que se nos puede ocurrir es hacer las búsquedas empleando el like del lenguaje SQL de la base de datos relacional que usemos. Sin embargo, el like de SQL tiene varias limitaciones y además es lento, supone una carga para la base de datos y las coincidencias son muy limitadas no teniendo en consideración peculiaridades del idioma como tildes y aproximaciones. Para tratar de resolver estos problemas podemos usar la librería Hibernate Search que a partir de las clases de dominio y de las propiedades sobre las que queramos hacer búsquedas creará un indice de Lucene para realizar búsquedas más rápidamente y con mejores resultados.

Hibernate Search
Con Hibernate Search que se apoya en Lucene podemos obtener resultados que son aproximaciones a la palabra búsqueda, por ejemplo, si buscamos «refactor» podemos obtener coincidencias para las palabras «refactors», «refactored» y «refactoring» en el lenguaje inglés. Cada lenguaje tiene sus propias reglas de análisis para buscar estas aproximaciones y hay analizadores para la mayoría de lenguajes. Además, podemos obtener una aproximación de las coincidencias encontradas totales al estilo de como hace Google.

Continuando el ejemplo de como usar Hibernate en una aplicación «standalone» vamos a ver que hay que hacer para crear el índice y como realizar una búsqueda empleando Hibernate Search.

SQL
Otra alternativa a Hibernate Search es si la base de datos soporta «full text search», es decir, el motor de la base de datos soporta en la sintaxis de las sentencias SQL búsquedas de texto completo. En MySQL es posible pero hasta la versión 5.5 solo si la tabla está definida con MyISAM aunque a partir de la versión 5.6 es posible hacerlo con InnoDB que es el modelo de almacenamiento recomendado. La sintaxis de la sentencia SQL para MySQL sería:

En PostgreSQL la sintaxis «full text search» es diferente:


Aunque con soluciones específicas del motor de la base de datos como esta perdemos la abstracción de la base de datos que proporciona Hibernate nos evitamos el tener que mantener el índice de Lucene con Hibernate Search.

Elasticsearch
Otra posibilidad muy interesante y tan buena o mejor que las anteriores es utilizar elasticsearch aunque al igual que con Hibernate Search debamos mantener e índice y los datos sincronizados pero eso probablemente sea tema para otra entrada :).

Referencia:
Código fuente búsqueda con Hibernate Search
Internacionalización (i18n) de campos con Hibernate
http://wiki.apache.org/solr/LanguageAnalysis
http://eraunatonteria.wordpress.com/tag/full-text-search/
http://dev.mysql.com/doc/refman/5.0/es/fulltext-search.html