PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como indexar uma tabela postgres por nome, quando o nome pode estar em qualquer idioma?


Se você deseja otimizar correspondências de substring arbitrárias, uma opção é usar o pg_tgrm módulo . Adicione um índice:
CREATE INDEX table_location_name_trigrams_key ON table
  USING gin (location_name gin_trgm_ops);

Isso quebrará "Simple Cafe" em "sim", "imp", "mpl", etc., e adicionará uma entrada ao índice para cada trigam em cada linha. O planejador de consulta pode usar automaticamente esse índice para correspondências de padrão de substring, incluindo:
SELECT * FROM table WHERE location_name ILIKE '%cafe%';

Essa consulta procurará "caf" e "afe" no índice, encontrará a interseção, buscará essas linhas e verificará cada linha em relação ao seu padrão. (Essa última verificação é necessária, pois a interseção de "caf" e "afe" corresponde a "simples café" e "inseguro scaffolding", enquanto "%cafe%" deve corresponder apenas a um). O índice se torna mais eficaz à medida que o padrão de entrada fica mais longo, pois pode excluir mais linhas, mas ainda não é tão eficiente quanto indexar palavras inteiras, portanto, não espere uma melhoria de desempenho em relação a to_tsvector .

O problema é que os trigramas não funcionam para padrões com menos de três caracteres. Isso pode ou não ser um fator decisivo para sua aplicação.

Editar: Eu inicialmente adicionei isso como um comentário.

Eu tive outro pensamento ontem à noite quando eu estava quase dormindo. Faça um cjk_chars função que recebe uma string de entrada, regexp_matches todos os intervalos CJK Unicode e retorna uma matriz de quaisquer desses caracteres ou NULL se nenhum. Adicione um índice GIN em cjk_chars(location_name) . Em seguida, consulte:
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!