Re: Búsqueda de palabras con Acentos

From: Gunnar Wolf <gwolf(at)gwolf(dot)org>
To: José Manuel Ruiz <josemanuelruizbaena(at)gmail(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Búsqueda de palabras con Acentos
Date: 2010-09-23 18:56:10
Message-ID: 20100923185610.GH23660@gwolf.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

José Manuel Ruiz dijo [Tue, Sep 21, 2010 at 05:59:59PM +0200]:
> Buenas.
>
> Tengo un problema con una base de datos PostgreSQL con codificación UNICODE
> que da soporte a una aplicación en PHP.
>
> Todo funcionaba correctamente hasta que me pidieron que una búsqueda de por
> ejemplo "Martin" debería devolver los registros "Martin" y también los
> "Martín".
>
> ¿Cómo puedo solucionar esto? Ya utilizo ilike en lugar de like para que no
> distinta entre "Martin" y "martin".
>
> No me preocupaba hasta que me dí cuenta de que MySQL con codificación
> utf8_general lo hace sin problemas. ¿Hay alguna solución para esto?

Ummm... Creo que -en líneas generales- estás buscando una solución
demasiado angosta ;-)

Si vas a hacer búsquedas sobre texto completo, y si quieres que además
estas búsquedas identifiquen palabras relacionadas (como Martin por
Martín, o como "educativo" por "educar"), puedes hacer tus búsquedas
usando TSearch2. Esto implica que manejes un trigger al crear o
modificar tus datos. Pero las ganancias bien valen la pena:

Carga primero las definiciones de tsearch2 - en mi caso (Debian, para
la DB 'test'):

$ psql test < /usr/share/postgresql/9.0/contrib/tsearch2.sql

Y ya desde psql

test=# select set_curcfg('spanish');
set_curcfg
------------

(1 row)

test=# CREATE TABLE blah (id serial, datos text, datos_vect tsvector);
NOTICE: CREATE TABLE will create implicit sequence "blah_id_seq" for
serial column "blah.id"
CREATE TABLE
test=# CREATE INDEX blah_idx ON blah USING gist(datos_vect);
CREATE INDEX
test=# CREATE TRIGGER vect_update BEFORE UPDATE OR INSERT ON blah FOR
EACH ROW EXECUTE PROCEDURE tsearch2(datos_vect, datos);
CREATE TRIGGER

Le aventamos algunos datos:

test=# INSERT INTO blah (datos) VALUES ('Martín martillaba educativos educadamente');
INSERT 0 1
test=# INSERT INTO blah (datos) VALUES ('¿Qué es lo que dices que Martin Martillaba?');
INSERT 0 1
test=# INSERT INTO blah (datos) VALUES ('Claramente he dicho que Martín martillaba educativos educadamente');
INSERT 0 1
test=# INSERT INTO blah (datos) VALUES ('Tu enunciado carece de educación. O por lo menos, carece de consistencia interna. Es incomprensible.');
INSERT 0 1
test=# INSERT INTO blah (datos) VALUES ('Entonces no hablamos de Martin, sino que de mi!');
INSERT 0 1

Y hacemos una consulta simple (con la sintaxis adecuada para
TSearch2):

test=# SELECT id, datos from blah where datos_vect @@ to_tsquery('Martín');
id | datos
----+-------------------------------------------------------------------
1 | Martín martillaba educativos educadamente
2 | ¿Qué es lo que dices que Martin Martillaba?
3 | Claramente he dicho que Martín martillaba educativos educadamente
5 | Entonces no hablamos de Martín, sino que de mi!
(4 rows)
id | datos
----+------------------------------------------------------------------------------------------------------
1 | Martín martillaba educativos educadamente
3 | Claramente he dicho que Martín martillaba educativos educadamente
4 | Tu enunciado carece de educación. O por lo menos, carece de consistencia interna. Es incomprensible.
(3 rows)

Bueno, y basta de trucos de mago. ¿Cómo ocurre esto en verdad? Veamos
qué es lo que en realidad estoy preguntando:

test=# select to_tsquery('Educar'), to_tsquery('Martín');
to_tsquery | to_tsquery
------------+------------
'educ' | 'martin'
(1 row)

¿Y cómo están guardados los datos para responder a esta solicitud?

test=# select datos_vect from blah;
datos_vect
--------------------------------------------------------------------------------------
'educ':3,4 'martill':2 'martin':1
'dic':5 'martill':8 'martin':7
'clar':1 'dich':3 'educ':7,8 'martill':6 'martin':5
'carec':3,10 'consistent':12 'educ':5 'enunci':2 'incomprens':15 'intern':13 'men':9
'entonc':1 'habl':3 'martin':5 'sin':6
(5 rows)

Espero que te sea más útil que simplemente botar acentos ;-)

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Carlos Bazán 2010-09-23 19:12:27 Re: Migracion de 8.4 a 9 (problemas con libperl.so)
Previous Message Jaime Casanova 2010-09-23 18:25:43 Re: Migracion de 8.4 a 9 (problemas con libperl.so)