Skip site navigation (1) Skip section navigation (2)

Re: Búsque?==?utf-8?Q?da 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úsque?==?utf-8?Q?da de palabras con Acentos
Date: 2010-09-23 18:56:10
Message-ID: 20100923185610.GH23660@gwolf.org (view raw or flat)
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

pgsql-es-ayuda by date

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

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group