PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL, Trigramme und Ähnlichkeit

Das Konzept der Trigrammähnlichkeit beruht darauf, dass jeder Satz in „Trigramme“ (Sequenzen von drei aufeinanderfolgenden Buchstaben) unterteilt wird und das Ergebnis als SET behandelt wird (d. h.:die Reihenfolge spielt keine Rolle, und Sie haben keine wiederholten Werte). Bevor der Satz betrachtet wird, werden zwei Leerzeichen am Anfang und eines am Ende hinzugefügt, und einzelne Leerzeichen werden durch doppelte ersetzt.

Trigramme sind ein Sonderfall von N-grams .

Das Trigramm-Set, das "Chateau blanc" entspricht, wird gefunden, indem alle Folgen von drei Buchstaben gefunden werden, die darauf erscheinen:

  chateau  blanc
---                 => '  c'
 ---                => ' ch'
  ---               => 'cha'
   ---              => 'hat'
    ---             => 'ate'
     ---            => 'tea'
      ---           => 'eau'
       ---          => 'au '
        ---         => 'u  '
         ---        => '  b'
          ---       => ' bl'
           ---      => 'bla'
            ---     => 'lan'
             ---    => 'anc'
              ---   => 'nc '

Wenn Sie sie sortieren und Wiederholungen entfernen, erhalten Sie:

'  b'
'  c'
' bl'
' ch'
'anc'
'ate'
'au '
'bla'
'cha'
'eau'
'hat'
'lan'
'nc '
'tea'

Diese kann von PostgreSQL mit der Funktion show_trgm berechnet werden :

SELECT show_trgm('Chateau blanc') AS A

A = [  b,  c, bl, ch,anc,ate,au ,bla,cha,eau,hat,lan,nc ,tea]

... die 14 Trigramme hat. (Überprüfen Sie pg_trgm ).

Und das Trigramm-Set, das "Chateau Cheval Blanc" entspricht, ist:

SELECT show_trgm('Chateau Cheval Blanc') AS B 

B = [  b,  c, bl, ch,anc,ate,au ,bla,cha,che,eau,evl,hat,hev,la ,lan,nc ,tea,vla]

... die 19 Trigramme hat

Wenn Sie zählen, wie viele Trigramme beide Gruppen gemeinsam haben, stellen Sie fest, dass sie die folgenden haben:

A intersect B = 
    [  b,  c, bl, ch,anc,ate,au ,bla,cha,eau,hat,lan,nc ,tea]

und die, die sie insgesamt haben, sind:

A union B = 
    [  b,  c, bl, ch,anc,ate,au ,bla,cha,che,eau,evl,hat,hev,la ,lan,nc ,tea,vla]

Das heißt, beide Sätze haben 14 gemeinsame Trigramme und insgesamt 19.
Die Ähnlichkeit wird berechnet als:

 similarity = 14 / 19

Sie können es überprüfen mit:

SELECT 
    cast(14.0/19.0 as real) AS computed_result, 
    similarity('Chateau blanc', 'chateau cheval blanc') AS function_in_pg

und Sie werden sehen, dass Sie Folgendes erhalten:0.736842

... was wie erklärt Ähnlichkeit berechnet wird, und warum Sie erhalten die Werte, die Sie erhalten.

HINWEIS:Sie können den Schnittpunkt und die Vereinigung berechnen mit:

SELECT 
   array_agg(t) AS in_common
FROM
(
    SELECT unnest(show_trgm('Chateau blanc')) AS t 
    INTERSECT 
    SELECT unnest(show_trgm('chateau chevla blanc')) AS t
    ORDER BY t
) AS trigrams_in_common ;

SELECT 
   array_agg(t) AS in_total
FROM
(
    SELECT unnest(show_trgm('Chateau blanc')) AS t 
    UNION 
    SELECT unnest(show_trgm('chateau chevla blanc')) AS t
) AS trigrams_in_total ;

Und dies ist eine Möglichkeit, die Ähnlichkeit verschiedener Satzpaare zu untersuchen:

WITH p AS
(
    SELECT 
      'This is just a sentence I''ve invented'::text AS f1,
      'This is just a sentence I''ve also invented'::text AS f2
),
t1 AS
(
    SELECT unnest(show_trgm(f1)) FROM p
),
t2 AS
(
    SELECT unnest(show_trgm(f2)) FROM p
),
x AS
(
    SELECT
        (SELECT count(*) FROM 
            (SELECT * FROM t1 INTERSECT SELECT * FROM t2) AS s0)::integer AS same,
        (SELECT count(*) FROM 
            (SELECT * FROM t1 UNION     SELECT * FROM t2) AS s0)::integer AS total,
        similarity(f1, f2) AS sim_2
FROM
    p 
)
SELECT
    same, total, same::real/total::real AS sim_1, sim_2
FROM
    x ;

Sie können es unter Rextester überprüfen