Full Text Search Postgre SQL
Full Text Search Postgre SQL
Full Text Search Postgre SQL
Introducción
Uno de los aspectos decisivos para el éxito o fracaso de un proyecto de software es su sistema de
búsquedas y la calidad de los resultados que provee al usuario final.
A lo largo de este artículo veremos las posibilidades que nos ofrece PostgreSQL para la
implementación de un sistema de recuperación de información simple pero muy potente.
Preparando el terreno de juego
Para empezar cabe señalar que en este artículo utilizaremos la versión 8.3 de PostgreSQL, dado
que a partir de ésta versión el módulo de Full Text Search se encuentra incluido dentro del core
del motor de bases de datos, evitándonos el tener que incluir dichas funcionalidades haciendo uso
de los contrib que vienen junto a la distribución principal de PostgreSQL.
Para empezar vamos a crear una estructura y unos usuarios que nos permitan trabajar
correctamente.
Como fuente de datos utilizaremos unos cuantos artículos publicados en ATIX tomados al azar,
empecemos.
Crearemos una base de datos y un usuario:
CREATE DATABASE FTS_prueba;
CREATE USER fts_user;
ALTER DATABASE FTS_prueba OWNER fts_user;
ALTER USER fts_user PASSWORD '*********';
Utilizaremos una tabla similar a ésta en la que se almacenarán los artículos publicados.
CREATE TABLE articulo
(
id serial NOT NULL,
texto text NOT NULL,
titulo text NOT NULL,
autor character varying(200) NOT NULL,
texto_tsv tsvector NOT NULL,
CONSTRAINT articulo_pkey PRIMARY KEY (id)
)
Realizamos la búsqueda sobre la columna texto de nuestra tabla articulo y nos devolverá el(los)
titulo(s) del(los) articulo(s) en caso de que la búsqueda sea exitosa:
Si deseáramos realizar la búsqueda no solo sobre el cuerpo del artículo sino también sobre el
titulo, podemos modificar la consulta de este modo:
SELECT titulo
FROM articulo
WHERE to_tsvector('spanish', titulo || texto) @@ to_tsquery('framework &
php');
Si deseamos definir un índice que agrupe a más de una columna de nuestra tabla:
Resaltando resultados
Una característica interesante de los sistemas de búsqueda es la presentación que se hace de los
resultados resaltando la parte del documento que coincide con el criterio de búsqueda.
Cuando efectuamos una búsqueda en este tipo de sistemas podemos visualizar los fragmentos
del documento con un color diferente al del resto del texto.
Si queremos implementar esta característica en PostgreSQL y Full Text Search debemos hacer
uso de la función ts_headline() que nos facilita los resultados de una consulta con una variedad de
opciones que veremos a continuación.
SELECT ts_headline('spanish', 'Se dice que un hombre debería hacer 3 cosas
importantes en su vida: tener un hijo, plantar un árbol y escribir un
libro; con un poco de analogía podríamos comenzar a contar la historia de
la comunidad ATIX, que empezó no teniendo un hijo sino varios, hijos que
durante este tiempo le brindaron su tiempo y colaboración, poca o mucha no
interesa, lo importante es que colaboraron', to_tsquery('ATIX'));
El resultado por defecto es este:
"<b>ATIX</b>, que empezó no teniendo un hijo sino varios, hijos que
durante este tiempo le brindaron"
Obtenemos una parte pequeña del documento con la(s) partes que coinciden con el criterio de
búsqueda encerradas entre tags HTML <b>, insertar luego esta resultado en una plantilla HTML
es bastante trivial. Si deseamos definir otro tipo de resaltado de los resultados podemos hacer uso
de las opciones StarSel y StopSel de la siguiente forma:
SELECT ts_headline('spanish', 'Se dice que un hombre debería hacer 3 cosas
importantes en su vida: tener un hijo, plantar un árbol y escribir un
libro; con un poco de analogía podríamos comenzar a contar la historia de
la comunidad ATIX, que empezó no teniendo un hijo sino varios, hijos que
durante este tiempo le brindaron su tiempo y colaboración, poca o mucha no
interesa, lo importante es que colaboraron', to_tsquery('ATIX'), 'StartSel
= <i>, StopSel = </i>');
Devolviéndonos este resultado:
"<i>ATIX</i>, que empezó no teniendo un hijo sino varios, hijos que
durante este tiempo le brindaron"
Si queremos definir el número de palabras que deberá tener nuestro resultado podemos hacer
uso de las opciones MaxWords y MinWords así:
SELECT ts_headline('spanish', 'Se dice que un hombre debería hacer 3 cosas
importantes en su vida: tener un hijo, plantar un árbol y escribir un
libro; con un poco de analogía podríamos comenzar a contar la historia de
la comunidad ATIX, que empezó no teniendo un hijo sino varios, hijos que
durante este tiempo le brindaron su tiempo y colaboración, poca o mucha no
interesa, lo importante es que colaboraron', to_tsquery('ATIX'), 'StartSel
= <i>, StopSel = </i>, MinWords = 10, MaxWords = 20');
Ranking de resultados
Para finalizar este artículo veremos una última característica interesante, la del ranking de
resultados. Comúnmente podemos ver que cuando utilizamos el buscador de un sistema de
información obtenemos los resultados ordenados por algún criterio definido por su programador,
ya sea por la fecha de su publicación (los documentos mas recientes deberían ser mas
importantes) o por la posición de los documentos en una tabla en la base de datos (los
documentos insertados inicialmente serán los que se muestren primero).
Con PostgreSQL también tenemos la opción de devolver al usuario los resultados de sus
búsquedas ordenados por relevancia, tomando unos criterios como estos:
• Cuantas coincidencias tiene una búsqueda en un determinado documento.
• Que tan cercanas están esas coincidencias en dicho documento.
• En que parte del documento esta la coincidencia (si esta al principio del documento
debería ser mas relevante)
Con estos criterios, entre otros mas, se les asignan pesos a los resultados y conforme a dichos
pesos se mostrarán primero los resultados con mayor relevancia.
Para hacer uso de esta característica debemos utilizar la función ts_rank() de la siguiente forma:
SELECT titulo, autor, ts_rank(texto_tsv,
to_tsquery('spanish', 'Java')) AS ranking
FROM articulo
ORDER BY ranking DESC;
Cabe hacer notar que la ejecución de la función ts_rank() se la debe realizar pasándole como
parámetro un atributo del tipo tsvector, al contrario que las anteriores funciones que podíamos
pasarles textos simples, en este caso el parámetro texto_tsv es del tipo tsvector por lo que no
tenemos problema alguno.
A continuación podemos ver los resultados de una búsqueda utilizando la consulta “Java”, se
muestran todos los artículos con su respectivo ranking, en caso de tener un ranking de cero
significa que la consulta es negativa para ese documento:
Conclusiones
La utilización de PostgreSQL y su módulo de Full Text Search nos da dos grandes beneficios al
momento de desarrollar las funcionalidades de búsqueda en nuestros sistemas, por un lado
aprovechamos muchas características de los sistemas de recuperación de información que ya
están implementadas en el motor de base de datos y por otro lado, centralizamos el componente
de búsquedas de nuestro sistema en el mismo servidor.
Espero que a lo largo de este corto artículo haya podido mostrar que si elegimos PostgreSQL, el
camino hacia un sistema de búsquedas efectivo se hará más divertido e interesante.
Referencias
1. PostgreSQL: http://www.postgresql.org
2. Full Text Search en PostgreSQL:
http://www.postgresql.org/docs/8.3/static/textsearch.html