sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo indexar una tabla de postgres por nombre, cuando el nombre puede estar en cualquier idioma?

Si desea optimizar coincidencias de subcadenas arbitrarias, una opción es usar el pg_tgrm módulo . Añadir un índice:

CREATE INDEX table_location_name_trigrams_key ON table
  USING gin (location_name gin_trgm_ops);

Esto dividirá "Simple Cafe" en "sim", "imp", "mpl", etc., y agregará una entrada al índice para cada trigam en cada fila. El planificador de consultas puede usar automáticamente este índice para coincidencias de patrones de subcadenas, que incluyen:

SELECT * FROM table WHERE location_name ILIKE '%cafe%';

Esta consulta buscará "caf" y "afe" en el índice, encontrará la intersección, buscará esas filas y luego comparará cada fila con su patrón. (Esta última verificación es necesaria ya que la intersección de "café" y "afe" coincide con "café simple" y "andamio inseguro", mientras que "%café%" solo debe coincidir con uno). El índice se vuelve más efectivo a medida que el patrón de entrada se alarga, ya que puede excluir más filas, pero aún no es tan eficiente como indexar palabras completas, así que no espere una mejora en el rendimiento con respecto a to_tsvector. .

El problema es que los trigramas no funcionan en absoluto para patrones que tienen menos de tres caracteres. Eso puede o no ser un factor decisivo para su aplicación.

Editar: Inicialmente agregué esto como un comentario.

Tuve otro pensamiento anoche cuando estaba casi dormido. Haz un cjk_chars función que toma una cadena de entrada, regexp_matches los rangos completos de CJK Unicode y devuelve una matriz de dichos caracteres o NULL si ninguno Agrega un índice GIN en cjk_chars(location_name) . Luego consulta por:

WHERE CASE
  WHEN cjk_chars('query') IS NOT NULL THEN
    cjk_chars(location_name) @> cjk_chars('query')
    AND location_name LIKE '%query%'
  ELSE
    <tsvector/trigrams>
  END

¡Ta-da, unigramas!