F.35. pg_trgm — soporte para la similitud de texto mediante coincidencia de trigramas #

F.35.1. Conceptos de trigramas (o trigrafos)
F.35.2. Funciones y operadores
F.35.3. Parámetros GUC
F.35.4. Soporte para índices
F.35.5. Integración con búsquedas de texto
F.35.6. Referencias
F.35.7. Autores

El módulo pg_trgm proporciona funciones y operadores para determinar la similitud de texto alfanumérico basándose en la coincidencia de trigramas (trigrams), así como clases de operadores de índice que admiten búsquedas rápidas de cadenas similares.

Este módulo se considera confiable (trusted), es decir, puede ser instalado por usuarios que no sean superusuarios pero tengan privilegios CREATE en la base de datos actual.

F.35.1. Conceptos de trigramas (o trigrafos) #

Un trigram es un grupo de tres caracteres consecutivos tomados de una cadena. Podemos medir la similitud de dos cadenas contando el número de trigramas que comparten. Esta idea tan sencilla resulta ser muy eficaz para medir la similitud de palabras en muchos idiomas naturales.

Note

pg_trgm ignora los caracteres que no forman palabras (no alfanuméricos) al extraer trigramas de una cadena. Se considera que cada palabra tiene dos espacios en blanco como prefijo y un espacio en blanco como sufijo al determinar el conjunto de trigramas contenidos en la cadena. Por ejemplo, el conjunto de trigramas en la cadena cat es c, ca, cat y at . El conjunto de trigramas en la cadena foo|bar es f, fo, foo, oo , b, ba, bar y ar .

F.35.2. Funciones y operadores #

Las funciones proporcionadas por el módulo pg_trgm se muestran en la Table F.26, y los operadores en la Table F.27.

Table F.26. Funciones de pg_trgm

Función

Descripción

similarity ( text, text ) → real

Devuelve un número que indica qué tan similares son los dos argumentos. El rango del resultado va desde cero (lo que indica que las dos cadenas son completamente diferentes) hasta uno (lo que indica que las dos cadenas son idénticas).

show_trgm ( text ) → text[]

Devuelve un array con todos los trigramas de la cadena dada. (En la práctica esto es útil en raras ocasiones, excepto para depuración).

word_similarity ( text, text ) → real

Devuelve un número que indica la mayor similitud entre el conjunto de trigramas de la primera cadena y cualquier extensión continua de un conjunto ordenado de trigramas en la segunda cadena. Para más detalles, consulta la explicación más abajo.

strict_word_similarity ( text, text ) → real

Igual que word_similarity, pero obliga a que los límites de la extensión coincidan con los límites de las palabras. Dado que no tenemos trigramas que crucen palabras, esta función devuelve en realidad la mayor similitud entre la primera cadena y cualquier extensión continua de palabras de la segunda cadena.

show_limit () → real

Devuelve el umbral de similitud actual utilizado por el operador %. Esto establece la similitud mínima entre dos palabras para que se consideren lo suficientemente similares como para ser errores ortográficos la una de la otra, por ejemplo. (Obsoleto; en su lugar usa SHOW pg_trgm.similarity_threshold).

set_limit ( real ) → real

Establece el umbral de similitud actual que utiliza el operador %. El umbral debe estar entre 0 y 1 (el valor por defecto es 0.3). Devuelve el mismo valor que se le ha pasado. (Obsoleto; en su lugar usa SET pg_trgm.similarity_threshold).


Considera el siguiente ejemplo:

# SELECT word_similarity('word', 'two words');
 word_similarity
-----------------
             0.8
(1 row)

En la primera cadena, el conjunto de trigramas es {" w"," wo","wor","ord","rd "}. En la segunda cadena, el conjunto ordenado de trigramas es {" t"," tw","two","wo "," w"," wo","wor","ord","rds","ds "}. La extensión más similar de un conjunto ordenado de trigramas en la segunda cadena es {" w"," wo","wor","ord"}, y la similitud es 0.8.

Esta función devuelve un valor que se puede entender aproximadamente como la mayor similitud entre la primera cadena y cualquier subcadena de la segunda cadena. Sin embargo, esta función no añade relleno a los límites de la extensión. Por lo tanto, no se considera la cantidad de caracteres adicionales presentes en la segunda cadena, excepto por los límites de las palabras que no coinciden.

Al mismo tiempo, strict_word_similarity selecciona una extensión de palabras en la segunda cadena. En el ejemplo anterior, strict_word_similarity seleccionaría la extensión de una sola palabra 'words', cuyo conjunto de trigramas es {" w"," wo","wor","ord","rds","ds "}.

# SELECT strict_word_similarity('word', 'two words'), similarity('word', 'words');
 strict_word_similarity | similarity
------------------------+------------
               0.571429 |   0.571429
(1 row)

Por lo tanto, la función strict_word_similarity es útil para encontrar la similitud con palabras completas, mientras que word_similarity es más adecuada para encontrar la similitud para partes de palabras.

Table F.27. Operadores de pg_trgm

Operador

Descripción

text % textboolean

Devuelve true si sus argumentos tienen una similitud mayor que el umbral de similitud actual establecido por pg_trgm.similarity_threshold.

text <% textboolean

Devuelve true si la similitud entre el conjunto de trigramas en el primer argumento y una extensión continua de un conjunto de trigramas ordenados en el segundo argumento es mayor que el umbral de similitud de palabras actual establecido por el parámetro pg_trgm.word_similarity_threshold.

text %> textboolean

Conmutador del operador <%.

text <<% textboolean

Devuelve true si su segundo argumento tiene una extensión continua de un conjunto de trigramas ordenados que coincide con los límites de las palabras, y su similitud con el conjunto de trigramas del primer argumento es mayor que el umbral de similitud estricta de palabras actual establecido por el parámetro pg_trgm.strict_word_similarity_threshold.

text %>> textboolean

Conmutador del operador <<%.

text <-> textreal

Devuelve la distancia entre los argumentos, que es uno menos el valor de similarity().

text <<-> textreal

Devuelve la distancia entre los argumentos, que es uno menos el valor de word_similarity().

text <->> textreal

Conmutador del operador <<->.

text <<<-> textreal

Devuelve la distancia entre los argumentos, que es uno menos el valor de strict_word_similarity().

text <->>> textreal

Conmutador del operador <<<->.


F.35.3. Parámetros GUC #

pg_trgm.similarity_threshold (real) #

Establece el umbral de similitud actual que utiliza el operador %. El umbral debe estar entre 0 y 1 (el valor por defecto es 0.3).

pg_trgm.word_similarity_threshold (real) #

Establece el umbral de similitud de palabras actual que utilizan los operadores <% y %>. El umbral debe estar entre 0 y 1 (el valor por defecto es 0.6).

pg_trgm.strict_word_similarity_threshold (real) #

Establece el umbral de similitud estricta de palabras actual que utilizan los operadores <<% y %>>. El umbral debe estar entre 0 y 1 (el valor por defecto es 0.5).

F.35.4. Soporte para índices #

El módulo pg_trgm proporciona clases de operadores de índices GiST y GIN que te permiten crear un índice sobre una columna de tipo text con el fin de realizar búsquedas de similitud muy rápidas. Estos tipos de índices admiten los operadores de similitud descritos anteriormente y, adicionalmente, admiten búsquedas de índices basadas en trigramas para consultas LIKE, ILIKE, ~, ~* y =. Las comparaciones de similitud no distinguen entre mayúsculas y minúsculas en una compilación por defecto de pg_trgm. Los operadores de desigualdad no están admitidos. Ten en cuenta que estos índices pueden no ser tan eficientes como los índices B-tree ordinarios para el operador de igualdad.

Ejemplo:

CREATE TABLE test_trgm (t text);
CREATE INDEX trgm_idx ON test_trgm USING GIST (t gist_trgm_ops);

o

CREATE INDEX trgm_idx ON test_trgm USING GIN (t gin_trgm_ops);

La clase de operadores GiST gist_trgm_ops aproxima un conjunto de trigramas como una firma de mapa de bits (bitmap signature). Su parámetro entero opcional siglen determina la longitud de la firma en bytes. La longitud por defecto es 12 bytes. Los valores válidos de la longitud de la firma están entre 1 y 2024 bytes. Las firmas más largas conducen a una búsqueda más precisa (escaneando una fracción más pequeña del índice y menos páginas de heap), a costa de un índice de mayor tamaño.

Ejemplo de creación de este tipo de índice con una longitud de firma de 32 bytes:

CREATE INDEX trgm_idx ON test_trgm USING GIST (t gist_trgm_ops(siglen=32));

A partir de este momento, tendrás un índice en la columna t que puedes usar para búsquedas de similitud. Una consulta típica es:

SELECT t, similarity(t, 'word') AS sml
  FROM test_trgm
  WHERE t % 'word'
  ORDER BY sml DESC, t;

Esto devolverá todos los valores en la columna de texto que sean lo suficientemente similares a word, ordenados del mejor resultado al peor. El índice se utilizará para que esta sea una operación rápida incluso sobre conjuntos de datos muy grandes.

Una variante de la consulta anterior es:

SELECT t, t <-> 'word' AS dist
  FROM test_trgm
  ORDER BY dist LIMIT 10;

Esto puede implementarse de manera bastante eficiente mediante índices GiST, pero no con índices GIN. Generalmente superará a la primera formulación cuando solo se desee un número pequeño de las coincidencias más cercanas.

También puedes usar un índice en la columna t para similitud de palabras o similitud estricta de palabras. Las consultas típicas son:

SELECT t, word_similarity('word', t) AS sml
  FROM test_trgm
  WHERE 'word' <% t
  ORDER BY sml DESC, t;

y

SELECT t, strict_word_similarity('word', t) AS sml
  FROM test_trgm
  WHERE 'word' <<% t
  ORDER BY sml DESC, t;

Esto devolverá todos los valores en la columna de texto para los cuales existe una extensión continua en el conjunto de trigramas ordenados correspondiente que es lo suficientemente similar al conjunto de trigramas de word, ordenados del mejor resultado al peor. El índice se utilizará para hacer de esta una operación rápida incluso sobre conjuntos de datos muy grandes.

Las posibles variantes de las consultas anteriores son:

SELECT t, 'word' <<-> t AS dist
  FROM test_trgm
  ORDER BY dist LIMIT 10;

y

SELECT t, 'word' <<<-> t AS dist
  FROM test_trgm
  ORDER BY dist LIMIT 10;

Esto puede implementarse de manera bastante eficiente mediante índices GiST, pero no con índices GIN.

A partir de PostgreSQL 9.1, estos tipos de índices también admiten búsquedas de índices para LIKE y ILIKE, por ejemplo:

SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';

La búsqueda del índice funciona extrayendo trigramas de la cadena de búsqueda y luego buscándolos en el índice. Cuantos más trigramas haya en la cadena de búsqueda, más eficaz será la búsqueda del índice. A diferencia de las búsquedas basadas en B-tree, la cadena de búsqueda no necesita estar anclada a la izquierda.

A partir de PostgreSQL 9.3, estos tipos de índices también admiten búsquedas de índices para coincidencias de expresiones regulares (operadores ~ y ~*), por ejemplo:

SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';

La búsqueda del índice funciona extrayendo trigramas de la expresión regular y luego buscándolos en el índice. Cuantos más trigramas se puedan extraer de la expresión regular, más eficaz será la búsqueda del índice. A diferencia de las búsquedas basadas en B-tree, la cadena de búsqueda no necesita estar anclada a la izquierda.

Tanto para las búsquedas con LIKE como con expresiones regulares, ten en cuenta que un patrón sin trigramas extraíbles degenerará en un escaneo completo del índice.

La elección entre la indexación GiST y GIN depende de las características de rendimiento relativas de GiST y GIN, que se discuten en otra parte de la documentación.

F.35.6. Referencias #

Sitio de desarrollo de GiST: http://www.sai.msu.su/~megera/postgres/gist/

Sitio de desarrollo de Tsearch2: http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/

F.35.7. Autores #

Oleg Bartunov , Moscú, Universidad de Moscú, Rusia

Teodor Sigaev , Moscú, Delta-Soft Ltd., Rusia

Alexander Korotkov , Moscú, Postgres Professional, Rusia

Documentación: Christopher Kings-Lynne

Este módulo está patrocinado por Delta-Soft Ltd., Moscú, Rusia.