Estou tentando criar um índice GIN para pesquisa de texto completo em um campo que pode conter texto em um dos vários idiomas diferentes. Os idiomas são predefinidos e saberemos em qual idioma queremos pesquisar no momento da consulta. Aqui está o esquema que eu tenho até agora ...
CREATE SCHEMA source;
CREATE SCHEMA common;
CREATE TABLE common.lang (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
code TEXT NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
INSERT INTO common.lang (name, code) VALUES
('english', 'en'),
('arabic', 'ar'),
('chinese', 'zh'),
('undefined', 'und');
CREATE TABLE source.user (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
screen_name TEXT NOT NULL UNIQUE,
profile_lang_id INTEGER NOT NULL REFERENCES common.lang(id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE INDEX source_user_names_idx ON source.user USING GIN (to_tsvector(SELECT common.lang.name FROM source.user INNER JOIN common.lang ON common.lang.id = source.user.profile_lang_id, name || ' ' || screen_name));
Ele relata um erro de sintaxe em ou próximo a "SELECT", o que faz sentido ... eu não acho que poderia apenas calçar uma instrução select lá, mas não tenho certeza de como usar corretamente uma instrução select dentro da chamada to_tsvector .
Eu olhei https://stackoverflow.com/a/21299033/4471711 , no entanto, isso codifica os idiomas, enquanto eu quero que os idiomas sejam extraídos de uma tabela dinamicamente no momento da criação do índice. Obviamente, se/quando adicionamos um idioma, precisaríamos recriar o índice.
Eu também olhei https://stackoverflow.com/a/15135730/4471711 , no entanto, isso não é compatível com a criação de um índice e requer apenas 1 parâmetro para to_tsvector, enquanto pareço precisar passar o idioma e o texto coluna.
Também estou tentando criar um índice de pesquisa de texto completo em um campo mais estilo documento, como abaixo:
CREATE TABLE source.post (
id BIGSERIAL PRIMARY KEY,
text TEXT NOT NULL
);
CREATE INDEX status_text_idx ON source.post USING GIN (to_tsvector(common_lang_id, text));
Novamente, com o índice acima, quero usar também o idioma especificado pela chave estrangeira para a tabela lang.
Minhas duas perguntas são:
Como uso corretamente a instrução SELECT para pegar o idioma da tabela lang usando sua chave estrangeira na tabela do usuário?
E se o lang for "indefinido" como é uma das opções? Eu não me importaria de padronizar o inglês para fins da chamada to_tsvector... Como eu adiciono esse padrão enquanto ainda permito que a tabela do usuário faça referência a "indefinido"?
default-text-search-config
Gambiarra
No entanto, você pode usar funções em um índice. E as funções podem referenciar tabelas externas. Dito isso, usar isso é meio que hack porque alterar a tabela (
common.lang
) exigirá a reindexação e a limpeza do cache da sessão.Você pode marcar funções como o
IMMUTABLE
que torna isso permitido. Se a tabela subjacente sofrer mutação, você terá que usarREINDEX
o index. Em projetos que usam esse hack, como PostGIS, eles recriam índices em lançamentos pontuais.Acompanhamento
A pesquisa de texto completo não está lá para fazer o que você acha que faz. Não está lá para pesquisar vários campos. Ele está lá para vetorizar o conteúdo das palavras e fazer uso de dicionários, stubbing, lexers, gazetteers, eliminação de palavras de parada e uma série de outros truques que nenhum deles se aplica. Se isso não faz sentido para você, você terá que ler os documentos. Se o que você quer é grep, o FTS raramente é o que você quer. Se você deseja grep em pequenos pedaços de texto não padrão (como nomes), não é o que você deseja. O que você provavelmente deseja indexação de trigramas.
Se tudo o que você quer é um
%term%
em dois campos, é melhor fazer isso com um índice de trigrama .Ou melhor ainda,