viernes, 21 de febrero de 2014

NEAR en MySQL

MySQL ofrece a través del MATCH AGAINST una serie de funcionalidades "avanzadas" de búsqueda, que pueden aprovecharse de los índices fulltext. Concretamente con el Boolean mode, podemos buscar cuando están o no unas determinadas palabras, otorgar pesos, truncamiento...
Pero podemos necesitar la funcionalidad NEAR que ofrecen los motores de búsquedas, como el Sphinx.

NEAR sirve para buscar registros en los que unas determinadas palabras aparezcan a determinada distancia la una de la otra, por ejemplo, para el registro:
Esta mañana el presidente del gobierno ha desayunado con el ministro de agricultura
La query con la condición presidente NEAR/6 ministro devolvería el registro indicado, mientras que NEAR/3 o NEAR/4 no lo encontrarían.
Básicamente es un método para asegurarnos de que las palabras que buscamos están cerca, y por lo tanto, que sea más probable que se refieran al mismo contexto.

Si tratamos de aplicar expresiones regulares directamente sobre los registros, y tenemos un gran volumen de datos (muchos registros y mucho texto en cada uno de ellos), veremos que la ejecución es excesivamente lenta.

La idea consiste en aprovechar los índices fulltext para filtrar rápidamente el número de posibles "candidatos", y luego aplicar la expresión regular para confirmar que las palabras se encuentran a la distancia deseada. Cuantas más palabras metamos en el proceso, la expresión regular se volverá más compleja, pero a su vez el número de registros candidatos será cada vez menor.

Además podemos usar algo del tipo NEAR/2-5, de forma que las palabras tengan que estar separadas por 2,3,4 o 5 palabras intermedias. NEAR/0-5, NEAR/5-5,...

Supongamos que tenemos una tabla NOTICIAS con (entre otros) un campo TEXTO que contiene el texto de nuestras noticias (se supone que TEXTO tiene el ínidice fulltext creado), veamos cómo quedaría la query:

SELECT * FROM NOTICIAS WHERE MATCH (TEXTO) AGAINST ('+presidente +ministro' in boolean mode) AND TEXTO REGEXP 'presidente([[:space:][:punct:]]+[^[:space:]]+){0,6}[[:space:][:punct:]]+ministro'

El + delante de las palabras en el AGAINS en boolean mode nos sirve para asegurarnos de que dichas palabras están en el registro que vamos a analizar, y será lo que nos permita tener un buen filtrado para que la query sea lo más rápida posible. No voy a detenerme mucho en explicar la expresión regular, ya que hay mucha documentación al respecto en la web.

Queda como ejercicio al lector jugar con la expresión regular para hacer el NEAR en los dos sentidos o añadir o quitar determinados caracteres... Lo importante es intentar mantenerla lo más simplificada posible, ya que la complejidad aumenta muy rápidamente.

No hay comentarios:

Publicar un comentario