PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 16.6 » Annexes » Modules et extensions supplémentaires fournis » fuzzystrmatch -- déterminer les similarités et les distances sur des chaînes de caractères

F.17. fuzzystrmatch -- déterminer les similarités et les distances sur des chaînes de caractères #

Le module fuzzystrmatch fournit diverses fonctions qui permettent de déterminer les similarités et la distance entre des chaînes.

Attention

À présent, les fonctions soundex, metaphone, dmetaphone et dmetaphone_alt ne fonctionnent pas correctement avec les encodages multi-octets (comme l'UTF-8). Utilisez daitch_mokotoff ou levenshtein avec de telles données.

Ce module est considéré comme « trusted », ce qui signifie qu'il peut être installé par des utilisateurs simples (sans attribut SUPERUSER) et qui ont l'attribut CREATE sur la base de données courante.

F.17.1. Soundex #

Le système Soundex est une méthode qui permet d'associer des noms (ou des mots) dont la prononciation est proche en les convertissant dans le même code. Elle a été utilisée à l'origine par le « United States Census » en 1880, 1900 et 1910. Soundex n'est pas très utile pour les noms qui ne sont pas anglais.

Le module fuzzystrmatch fournit deux fonctions pour travailler avec des codes Soundex :

   soundex(text) returns text
   difference(text, text) returns int
  

La fonction soundex convertit une chaîne en son code Soundex. La fonction difference convertit deux chaînes en leur codes Soundex, puis rapporte le nombre de positions de code correspondant. Comme les codes Soundex ont quatre caractères, le résultat va de zéro à quatre. Zéro correspond à aucune correspondance, quatre à une correspondance exacte. (Du coup, la fonction est mal nommée -- similarity aurait été un meilleur nom.)

Voici quelques exemples d'utilisation :

SELECT soundex('hello world!');

SELECT soundex('Anne'), soundex('Ann'), difference('Anne', 'Ann');
SELECT soundex('Anne'), soundex('Andrew'), difference('Anne', 'Andrew');
SELECT soundex('Anne'), soundex('Margaret'), difference('Anne', 'Margaret');

CREATE TABLE s (nm text);

INSERT INTO s VALUES ('john');
INSERT INTO s VALUES ('joan');
INSERT INTO s VALUES ('wobbly');
INSERT INTO s VALUES ('jack');

SELECT * FROM s WHERE soundex(nm) = soundex('john');

SELECT * FROM s WHERE difference(s.nm, 'john') > 2;
  

F.17.2. Daitch-Mokotoff Soundex #

Tout comme le système original Soundex, Daitch-Mokotoff Soundex fait correspondre des noms se ressemblant en les convertissant vers le même code. Néanmoins, Daitch-Mokotoff Soundex est significativement plus utile pour les noms non-anglais que le système original. Les améliorations majeures sur le système original incluent :

  • Le code est basé sur les six premières lettres significatives plutôt que sur quatre.

  • Une lettre ou une combinaison de lettres correspond à dix codes possibles plutôt que sept.

  • Quand deux lettres consécutives ont un seul son, elles sont codées avec un seul numéro.

  • Quand une lettre ou une combinaison de lettres peut avoir différents sons, plusieurs codes sont émis pour couvrir toutes les possibilités.

Cette fonction génère les codes Daitch-Mokotoff soundex d'après son argument :

daitch_mokotoff(source text) returns text[]

Le résultat peut contenir un ou plusieurs codes suivant les prononciations plausibles, donc il est représenté sous la forme d'un tableau.

Comme un code Daitch-Mokotoff soundex consiste en seulement six chiffres, source devrait être de préférence un simple mot ou nom.

Voici quelques exemples :

SELECT daitch_mokotoff('George');
 daitch_mokotoff
-----------------
 {595000}

SELECT daitch_mokotoff('John');
 daitch_mokotoff
-----------------
 {160000,460000}

SELECT daitch_mokotoff('Bierschbach');
                      daitch_mokotoff
-----------------------------------------------------------
 {794575,794574,794750,794740,745750,745740,747500,747400}

SELECT daitch_mokotoff('Schwartzenegger');
 daitch_mokotoff
-----------------
 {479465}

Pour une correspondance entre des noms simples, les tableaux de texte renvoyés peuvent être comparés direction en utilisant l'opérateur && : toute surcharge peut être considéré comme une correspondance. Un index GIN pourrait être utilisé pour plus de performances, voir Chapitre 70 et cet exemple :

CREATE TABLE s (nm text);
CREATE INDEX ix_s_dm ON s USING gin (daitch_mokotoff(nm)) WITH (fastupdate = off);

INSERT INTO s (nm) VALUES
  ('Schwartzenegger'),
  ('John'),
  ('James'),
  ('Steinman'),
  ('Steinmetz');

SELECT * FROM s WHERE daitch_mokotoff(nm) && daitch_mokotoff('Swartzenegger');
SELECT * FROM s WHERE daitch_mokotoff(nm) && daitch_mokotoff('Jane');
SELECT * FROM s WHERE daitch_mokotoff(nm) && daitch_mokotoff('Jens');

Pour l'indexation et la correspondance de tout nombre de noms quelque soit l'ordre, les fonctionnalités de la recherche plein texte peuvent être utilisées. Voir Chapitre 12 et cet exemple :

CREATE FUNCTION soundex_tsvector(v_name text) RETURNS tsvector
BEGIN ATOMIC
  SELECT to_tsvector('simple',
                     string_agg(array_to_string(daitch_mokotoff(n), ' '), ' '))
  FROM regexp_split_to_table(v_name, '\s+') AS n;
END;

CREATE FUNCTION soundex_tsquery(v_name text) RETURNS tsquery
BEGIN ATOMIC
  SELECT string_agg('(' || array_to_string(daitch_mokotoff(n), '|') || ')', '&')::tsquery
  FROM regexp_split_to_table(v_name, '\s+') AS n;
END;

CREATE TABLE s (nm text);
CREATE INDEX ix_s_txt ON s USING gin (soundex_tsvector(nm)) WITH (fastupdate = off);

INSERT INTO s (nm) VALUES
  ('John Doe'),
  ('Jane Roe'),
  ('Public John Q.'),
  ('George Best'),
  ('John Yamson');

SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('john');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('jane doe');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('john public');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('besst, giorgio');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('Jameson John');

S'il est souhaité d'éviter de recalculer les codes soundex pendant une revérification d'index, un index sur une colonne séparée peut être utilisé à la place d'un index sur une expression. Une colonne stockée automatiquement générée peut être utilisée pour cela ; voir Section 5.3.

F.17.3. Levenshtein #

Cette fonction calcule la distance de Levenshtein entre deux chaînes :

levenshtein(source text, target text, ins_cost int, del_cost int, sub_cost int) returns int
levenshtein(source text, target text) returns int
levenshtein_less_equal(source text, target text, ins_cost int, del_cost int, sub_cost int, max_d int) returns int
levenshtein_less_equal(source text, target text, max_d int) returns int
  

La source et la cible (target) sont des chaînes quelconques non NULL de 255 caractères. Les paramètres de coût indiquent respectivement le coût d'une insertion, suppression ou substitution d'un paramètre. Vous pouvez omettre les paramètres de coût, comme dans la deuxième version de la version. Dans ce cas, elles ont 1 comme valeur par défaut.

levenshtein_less_equal est une version accélérée de la fonction Levenshtein à utiliser que lorsque de petites distances sont intéressantes. Si la distance réelle est inférieure ou égale à max_d, alors levenshtein_less_equal renvoie la bonne distance ; sinon elle renvoie une valeur supérieure à max_d. Si max_d est négatif, alors le comportement est identique à levenshtein.

Exemples :

test=# SELECT levenshtein('GUMBO', 'GAMBOL');
 levenshtein
-------------
           2
(1 row)

test=# SELECT levenshtein('GUMBO', 'GAMBOL', 2,1,1);
 levenshtein
-------------
           3
(1 row)

test=# SELECT levenshtein_less_equal('extensive', 'exhaustive',2);
 levenshtein_less_equal
------------------------
                      3
(1 row)

test=# SELECT levenshtein_less_equal('extensive', 'exhaustive',4);
 levenshtein_less_equal
------------------------
                      4
(1 row)
  

F.17.4. Metaphone #

Metaphone, comme Soundex, construit un code représentatif de la chaîne en entrée. Deux chaînes sont considérées similaires si elles ont le même code.

Cette fonction calcule le code metaphone d'une chaîne en entrée :

   metaphone(source text, max_output_length int) returns text
  

source doit être une chaîne non NULL de 255 caractères au maximum. max_output_length fixe la longueur maximale du code metaphone résultant ; s'il est plus long, la sortie est tronquée à cette taille.

Exemple

test=# SELECT metaphone('GUMBO', 4);
 metaphone
-----------
 KM
(1 row)
  

F.17.5. Double Metaphone #

Le système « Double Metaphone » calcule deux chaînes « qui se ressemblent » pour une chaîne en entrée -- une « primaire » et une « alternative ». Dans la plupart des cas, elles sont identiques mais, tout spécialement pour les noms autres qu'anglais, elles peuvent être légèrement différentes, selon la prononciation. Ces fonctions calculent le code primaire et le code alternatif :

dmetaphone(source text) returns text
dmetaphone_alt(source text) returns text
  

Il n'y a pas de limite de longueur sur les chaînes en entrée.

Exemple :

test=# select dmetaphone('gumbo');
 dmetaphone
------------
 KMP
(1 row)