FTS (I): Búsqueda De Texto Completo en PostgreSQL

- - publicado en Base de Datos etiquetado como fts, pgadmin, postgresql | Comentarios

Al final me dió por actualizar los PostgreSQL a la nueva versión 9.0, junto con el pgadmin3, y al entrar a la aplicación (versión 1.12.1) me encuentro que hay unos cuatro iconos nuevos: Configuraciones FTS, Diccionarios FTS, Analizadores FTS y Plantillas FTS. ¿y qué es todo esto? Fuente: documentación oficial de PostgreSQL 9.0.

El concepto de FTS

La búsqueda de texto completa (Full Text Searching o FTS) proporciona la capacidad de identificar documentos de lenguaje natural que satisfacen una consulta y, opcionalmente, ordenarlos por relevancia a la consulta. El tipo más común de búsqueda es buscar todos los documentos que contengan los términos de la consulta y los retorna en orden de similitud. Los conceptos de consulta y similitud son muy flexibles y dependen de la aplicación específica. La búsqueda más simple considera una consulta como un conjunto de palabras y su similitud con la frecuencia de aparición de las mismas en el documento.

¿Qué es un documento?

Un documento es la unidad de búsqueda en un sistema FTS; por ejemplo, un artículo de una revista o un mensaje de email. El motor de búsqueda de texto debe estar preparado para analizar documentos y almacenar asociaciones de lexemas (palabras clave) con su documento padre. Después, estas asociaciones son usadas para buscar documentos que contengan esas palabras clave.

Para PostgreSQL un documento es, normalmente, un campo de texto, o una concatenación de varios campos de texto almacenados en una o varias tablas, o un texto obtenido de forma dinámica. En otras palabras, un documento puede ser construido de diferentes formas y puede no estar almacenado en ningún sitio. Por ejemplo:

SELECT title || ' ' || author || ' ' || abstract || ' ' || body AS document
FROM messages
WHERE mid = 12;

Búsqueda de texto básica

El FTS en PostgreSQL está basada en el operador @@, el cual retorna true si un tsvector (documento) coincide con una tsquery (consulta). No importa el orden en el que se pongan:

SELECT 'tres tristes tigres comieron trigo de un trigal'::tsvector @@ 'tristes & tigres'::tsquery;

Búsqueda de Resultados por Ránking

Ránking intenta medir como de relevantes son los documentos para una consulta en particular, así que cuando hay muchas coincidencias, la más relevante se muestra primero. PostgreSQL proporciona dos funciones de ránking predefinidas, las cuales tienen en cuenta el léxico, proximidad y estructura de la información. Esto es, que consideran como aparecen de frecuentes los términos en el documento, como de juntos están en el documento y como de importante es la parte de el documento donde aparecen. Sin embargo, el concepto de relevancia es vago y muy específico de la aplicación. Aplicaciones diferentes pueden requerir información adicional para el ránking. Las funciones construidas para ránking son solo ejemplos. Puedes escribir tus propias funciones de ránking y/o combinar sus resultados con factores adicionales para ajustarlas a tus necesidades específicas.

Aquí hay un ejemplo que, selecciona solo las diez coincidencias más altas en el ránking:

SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

El resultado:

———————————————–+———- The Virgo Cluster: Hot Plasma and Dark Matter | 1.90953 </pre>

La misma usando un ranking normalizado:

SELECT title, ts_rank_cd(textsearch, query, 32 /* rank/(rank+1) */ ) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE  query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

Y su resultado:

———————————————–+——————- The Virgo Cluster: Hot Plasma and Dark Matter | 0.656301290640973 </pre>

¿Hay más?

Pues claaaaaro que sí. Pero de momento lo dejo aquí, en previsión de hacer una segunda entrega con cosas como resultados resaltados (highlighting results) y sobretodo, la personalización de los analizadores, plantillas, configuraciones y diccionarios.

Manuel Rubio

Manuel Rubio

Fundador de AltenWald

Comments