Re: error al usar variable text

From: Gunnar Wolf <gwolf(at)gwolf(dot)org>
To: Gabriel Ferro <gabrielrferro(at)yahoo(dot)com(dot)ar>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: error al usar variable text
Date: 2009-01-31 16:43:23
Message-ID: 20090131164322.GA24483@cajita.gateway.2wire.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Gabriel Ferro dijo [Fri, Jan 30, 2009 at 12:53:43PM -0800]:
> Alvaro, lo de hacer un nuevo mensaje no te entiendo, creo que el asunto es correcto.
> Segundo, plainto_tsquery no me sirve ya que no me da lo mismo
> ejemplo
> select 'hola coco'::tsvector;
> Rta: 'coco' 'hola'
> select plainto_tsquery('hola:coco');
> Rta: 'hol' & 'coc'

Es que no es lo mismo un tsvector y un tsquery - El tsvector es la
manera en que representas el contenido de un registro de manera
adecuada para la búsqueda en texto completo. Por ejemplo, de las
primeras líneas de tu correo:

gw=# select to_tsvector('spanish', '> Alvaro, lo de hacer un nuevo mensaje no te entiendo, creo que el asunto es corre
gw'# > Segundo, plainto_tsquery no me sirve ya que no me da lo mismo
gw'# > ejemplo
gw'# ');
to_tsvector
---------------------------------------------------------------------------------------------------------------------------------------------------------------
'da':27 'cre':11 'hac':4 'corr':16 'mism':29 'nuev':6 'sirv':22 'alvar':1 'asunt':14 'ejempl':30 'mensaj':7 'plaint':18 'segund':17 'entiend':10 'tsquery':19
(1 row)

Parece desordenado, pero eso porque sólo eres un humano. Puedes ver,
por ejemplo, que aparece la partícula 'alvar':1 - Eso significa que
una palabra cuya raiz es 'alvar' ('Alvaro', quitando la mayúscula y la
'o' que es indicativa de género) está en primer posición, y si haces
una búsqueda ordenada sobre 'Alvaro', tu correo debe aparecer como más
relevante que uno en el que éste nombre aparezca más
adelante... Claro, siempre que aparezca sólo una vez (porque en este
caso no se nota, pero las palabras duplicadas aparecen con más de un
número).

Notarás también que yo le especifiqué como primer argumento que mi
consulta sería en español. Si lo omito, supongo que PostgreSQL la hace
dependiendo del entorno en que sea llamado (en Unix, dependiendo de
$LC_ALL o $LANG). Mi equipo usa localización en inglés, por lo que:

gw=# select to_tsvector('> Alvaro, lo de hacer un nuevo mensaje no te entiendo, creo que el asunto es corre
gw'# > Segundo, plainto_tsquery no me sirve ya que no me da lo mismo
gw'# > ejemplo
gw'# ');
to_tsvector
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'da':27 'de':3 'el':13 'es':15 'lo':2,28 'te':9 'un':5 'ya':23 'que':12,24 'corr':16 'creo':11 'sirv':22 'hacer':4 'mismo':29 'nuevo':6 'alvaro':1 'asunto':14 'mensaj':7 'ejemplo':30 'plainto':18 'segundo':17 'tsqueri':19 'entiendo':10
(1 row)

el resultado es mucho más largo (lo cual _no_ es bueno). Si
especificas el lenguaje, el motor Snowball de TSearch va a hacer lo
posible por eliminar las partículas que no significan nada por ser
demasiado frecuentes (preposiciones, artículos, etc.) y buscar las
raíces léxicas. Puedes ver que en este caso, 'Alvaro' conserva la 'o'
que le confiere el género (y disculpa que te tome como ejemplo - Tú te
lo ganas por responder siempre ;-) ), porque en inglés esta 'o' sería
parte de la raiz. Si guardas tus tsvectors analizados en inglés, una
búsqueda sobre 'ejemplar' no va a coincidir con tu 'ejemplo'.

Bueno, ¿y tsquery?

Tsquery es ua estructura que te permite construir explícitamente
búsquedas a realizar sobre campos tsvector. No tiene sentido almacenar
un tsquery - debes buscar convertir a tsquery lo que tu usuario te
pida. Por ejemplo, si quieres buscar mensajes acerca de optimización
de índices en tablas grandes:

comas=# select plainto_tsquery('spanish', 'optimización de índices en tablas grandes');
plainto_tsquery
----------------------------------------
'optimiz' & 'indic' & 'tabl' & 'grand'
(1 row)

Antes de otra cosa, mira qué resulta si nuevamente omito el 'spanish':

comas=# select plainto_tsquery('optimización de índices en tablas grandes');
plainto_tsquery
-------------------------------------------------------------
'optimización' & 'de' & 'índice' & 'en' & 'tabla' & 'grand'
(1 row)

¿te queda más claro por qué explicitar el lenguaje?

Bueno, plainto_tsquery() te convierte a tsquery una cadena de texto
arbitrario, y muchas veces es lo que quieres ofrecer al usuario - pero
tsquery tiene un pequeño lenguaje que te permite gran riqueza por
medio de expresiones lógicas. Por ejemplo, posiblemente encuentres
varias redacciones que te lleven a lo mismo - Buscas optimización de
índices si quieres acelerar las búsquedas o mejorar la velocidad de
acceso, ¿cierto? Pero como ya hiciste tu tarea y leíste _todos_ los
mensajes de Álvaro, quieres ignorar esos resultados. Va, pues:

gw=# select to_tsquery('((optimización & de & índices | acelerando & las & busquedas | velocidad & de & acceso ) & tablas & grandes) & ! alvaro');
to_tsquery
----------------------------------------------------------------------------------------------------------------------------------------------
( ( 'optimización' & 'de' & 'índice' | 'acelerando' & 'las' & 'busqueda' ) | 'velocidad' & 'de' & 'acceso' ) & 'tabla' & 'grand' & !'alvaro'
(1 row)

Claro, toca al programador desarrollar la interfaz adecuada para
permitir estas búsquedas a los usuarios ;-) to_tsquery() es mucho más
potente que plainto_tsquery(), pero requiere pensarle un poquito más.

Espero que con esto te quede más claro.

> la funcion que me da el error es
> SELECT clave,datos,vectordatos
> FROM personas,
> to_tsquery('FERRO&GABRIEL') AS q
> WHERE vectordatos @@ q and
> ('Ocupa:Empleado':: tsquery @@ datos::tsvector)
> ORDER BY ts_rank_cd(vectordatos,q) DESC;
>
> al intentar hacer datos::tsvector y encontrar un : cargado en datos
>
> pense en reemplazar datos::tsvector por
> regexp_replace( datos, E'[\\s\'|:&()!]+',' ','g')::tsvector;
>
> pero que haga esto por cada fila que compara me parece que hara la
> consulta mas lenta. ¿considere todos los caracteres raros?. ¿que les
> parece?

Creo que esto viene de no usar un lenguaje significativo... La cadena
'ocupa:empleado' no tendría sentido para TSearch2, de hecho:

comas=# SELECT to_tsvector('spanish', 'ocupa:empleado');
to_tsvector
--------------------
'ocup':1 'emple':2
(1 row)

(y si busco sin 'spanish', da 'ocupa' y 'empleado'). Para esta
búsqueda, te sugiero una de dos: O normalizas la ocupación
convirtiéndola en una referencia a otra tabla (con lo que puedas decir
'AND ocupacion_id = 1'), o para esto haces una búsqueda textual sobre
los resultados (esto es, WHERE vectordatos @@ q AND datos like
'%Ocupa:Empleado%') - TSearch no está hecho más que para búsquedas de
texto "tokenizado" en palabras independientes, descartando todos los
caracteres no alfanuméricos.

Saludos,

--
Gunnar Wolf - gwolf(at)gwolf(dot)org - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Gunnar Wolf 2009-01-31 16:46:55 Re: Cómo listar secuencias?
Previous Message Jaime Casanova 2009-01-30 23:17:43 Re: [pgsql-es-ayuda] Hay relación entre una tabla y la Secuencia