SlideShare une entreprise Scribd logo
1  sur  112
Télécharger pour lire hors ligne
Full Text Search
-
Busca Textual no
PostgreSQL
Palestrante: Juliano Atanazio
O que é? Para que serve?
● Full Text Search / Text Search / Busca Textual: é
um mecanismo que possibilita identificar documentos
em linguagem natural que casem com uma consulta e
opcionalmente ordená-los por relevância.
● O uso mais comum de busca é encontrar todos
documentos que contém termos de uma consulta e
retorná-los conforme sua semelhança com essa
consulta.
Operadores ~, ~*, LIKE, and ILIKE
Por que NÃO?
● Não há suporte linguístico (mesmo para inglês);
● Expressões regulares não são suficientes, pois é difícil lidar com
derivações de palavras;
● Não tem ordem (relevância) de resultados de busca, o que os faz
ineficazes quando milhares de documentos que casem são
encontrados;
● Tendência a lentidão, por não haver suporte a índice, então eles
têm que processar todos documentos por cada busca.
Termos
● Documento
É a unidade de busca em um sistema de busca
textual, por exemplo: um artigo de revista ou uma
mensagem de e-mail.
Para buscas no PostgreSQL, um documento é
normalmente um campo de texto em uma linha de
uma tabela, ou possivelmente uma combinação
(concatenação) de campos.
Resumindo: documento em buscas textuais é um
texto.
Termos
SELECT titulo||' '||texto||' '||texto FROM tb_post WHERE id=1;
Laranjeira A laranja é o fruto produzido pela laranjeira (Citrus × sinensis), uma árvore da família Rutaceae. A 
laranja é um fruto híbrido, criado na antiguidade a partir do cruzamento da cimboa com a tangerina. O sabor da 
laranja varia do doce ao levemente ácido. Frequentemente, esta fruta é descascada e comida ao natural, ou 
espremida para obter sumo. As pevides (pequenos caroços duros) são habitualmente removidas, embora possam ser 
usadas em algumas receitas. A casca exterior pode ser usada também em diversos pratos culinários, como 
ornamento, ou mesmo para dar algum sabor. A camada branca entre a casca e as gomas, de dimensão variável, 
raramente é utilizada, apesar de ter um sabor levemente doce. É recomendada para "quebrar" o sabor ácido da 
laranja na boca, após terminar de consumir o fruto.
● Documento
Exemplo:
A partir da consulta extraiu-se o documento.
Termos
● Token
Tokens são as palavras em um documento, que
podem variar seus tipos como números, palavras,
palavras complexas e endereços de e-mail.
Exemplo:
O documento foi convertido em tokens.
SELECT
'O rato foi pego pela gata preta, pelo gato branco e pelo cachorro 
de pêlos lisos'::tsvector;
'O' 'branco' 'cachorro' 'de' 'e' 'foi' 'gata' 'gato' 'lisos' 'pego' 'pela' 'pelo' 'preta,' 'pêlos' 'rato'
SELECT to_tsvector('gatas');
'gat':1
Termos
● Lexema
Palavra ou parte da palavra que serve de base ao
sentido por ela. Similar ao conceito de radical em
gramática.
Exemplos:
SELECT to_tsvector('gato');
'gat':1
Termos
● Stop Words / Palavras de Parada
São palavras que podem ser consideradas irrelevantes para o conjunto
de resultados a ser exibido em uma busca realizada em um search
engine.
Exemplos:
Artigos: o, a, os, as, um, uma, uns, umas
Conjunções: e, nem, mas, já, mas, ou, que, se
Crase: à
Preposições: a, com, como, de, em, para, por, sem
Pronomes: eu, nós, tu, vós, ele, eles, ela, elas, seu, teu, meu, no, na, nos, nas, quem, que,
qual
Termos
Stop Words / Palavras de Parada
● O postgres lê o arquivo de palavras de parada que está em
$SHAREDIR/tsearch_data/ cuja extensão desse arquivo
é .stop.
Seu conteúdo é de apenas stop words.
● $SHAREDIR pode variar dependendo da instalação do
PostgreSQL. Por padrão é o diretório share da instalação.
● Para o idioma português o arquivo é
$SHAREDIR/tsearch_data/portuguese.stop
● Para obter o valor de $SHAREDIR, dê o comando no shell:
$ pg_config ­­sharedir
SELECT 'O rato foi pego pela gata preta, pelo gato branco e 
pelo cachorro de pêlos lisos'::tsvector;
'O' 'branco' 'cachorro' 'de' 'e' 'foi' 'gata' 'gato' 'lisos' 'pego' 'pela' 'pelo' 'preta,' 'pêlos' 'rato'
Pré Processamento
Documento LexemasTokens
1 2
Exemplos:
1)
2)
Cadê as stop words no 2???
SELECT to_tsvector('O rato foi pego pela gata preta, pelo gato
branco e pelo cachorro de pêlos liso');
'branc':10 'cachorr':13 'gat':6,9 'lis':16 'peg':4 'pret':7 'pêl':15 
'rat':2
Ajustando a Configuração de Busca Textual
● A funcionalidades de busca textual é controlada por configurações
de busca textual. O PostgreSQL vem com configurações pré
definidas para muitos idiomas.
● Para listar todas as configurações disponíveis, no psql, dê o comando:
● Para exibir qual é a configuração que está em uso na sessão:
● Essa configuração pode ser mudada para todo o cluster no postgresql.conf,
bastando apenas um reload no serviço ou mesmo para a sessão atual:
dF
SHOW default_text_search_config;
pg_catalog.english
SET default_text_search_config = 'pg_catalog.portuguese';
Tipos e Respectivas Funções
SELECT 'O carro correu, correu e venceu a corrida facilmente, 
ultrapassando o último carro a 15 min do final'::tsvector;
'15' 'O' 'a' 'carro' 'correu' 'correu,' 'corrida' 'do' 'e' 'facilmente,' 
'final' 'min' 'o' 'ultrapassando' 'venceu' 'último'
Tipo tsvector
● Vetor de lexemas e posições;
● Representa um documento em uma forma otimizada para buscas
de texto;
● Seu valor é uma lista ordenada de lexemas distintos;
● Ordena, elimina duplicações automaticamente;
● Representa um documento de forma compacta;
Tipos e Respectivas Funções
Tipo tsvector
● Opcionalmente, posições (em números inteiros) podem ser
anexadas aos lexemas:
SELECT 'o:1 carro:2 verde:3 correu:4 mais:5 do:6 que:7 o:8 
carro:9 vermelho:10'::tsvector;
'carro':2,9 'correu':4 'do':6 'mais':5 'o':1,8 'que':7 'verde':3 'vermelho':10
● Em caso de duplicações as posições são delimitadas por vírgulas.
SELECT to_tsvector('pg_catalog.portuguese',
'O carro correu, correu e venceu a corrida facilmente, 
ultrapassando o último carro a 15 min do final');
'15':15 'carr':2,13 'corr':3,4,8 'facil':9 'final':18 'min':16 'ultrapass':10 'venc':6 'últim':12
Tipos e Respectivas Funções
Função to_tsvector
● Converte um documento para tokens, reduz esses tokens para
lexemas e retorna um tsvector que lista os lexemas junto com
suas posições no documento.
● Stop words eliminadas!
SELECT 'rato gato pato'::tsvector;
 'gato' 'pato' 'rato'
Tipos e Respectivas Funções
Função to_tsvector
● to_tsvector != 'string'::tsvector
SELECT to_tsvector('rato gato pato');
 'gat':2 'pat':3 'rat':1
Tipos e Respectivas Funções
Tipo tsquery
● Consulta de busca textual;
● Representa um texto de consulta;
● Armazena lexemas que serão base de busca;
● Combinação de lexemas utilizando operadores booleanos:
& (AND), | (OR) e ! (NOT);
● Parênteses podem ser usados para reforçar um grupamento de
operadores.
Tipos e Respectivas Funções
Tipo tsquery
Exemplos:
SELECT 'gato & rato'::tsquery;
'gato' & 'rato'
SELECT 'pato & (gato|rato)'::tsquery;
'pato' & ( 'gato' | 'rato' )
SELECT '! 1'::tsquery;
!'1'
SELECT to_tsquery('pg_catalog.portuguese','!(correr & vencer)');
!( 'corr' & 'venc' )
Tipos e Respectivas Funções
Função to_tsquery
● Cria um valor tsquery de um querytext;
● Normaliza cada token em um lexema usando a configuração
especificada ou por omissão;
● Similar à função to_tsvector, em to_tsquery, podemos
determinar o idioma e normalizar os termos passados para seus
radicais:
SELECT to_tsquery('pg_catalog.english','!(running & winning)');
!( 'run' & 'win' )
Tipos e Respectivas Funções
Função to_tsquery
● Também similarmente à função to_tsvector, podemos omitir o
primeiro parâmetro da função, cujo efeito se dará por pegar a
configuração de busca textual padrão:
SELECT to_tsquery('!(correr & vencer)');
!( 'corr' & 'venc' )
Tipos e Respectivas Funções
Função plainto_tsquery
● Transforma texto sem formação querytext para tsquery;
● O texto é analisado e normalizado como se fosse um tsvector e
então o operador booleano & (AND) é inserido entre as palavras
sobreviventes:
SELECT plainto_tsquery('english', 'The Fat Rats are sleeping with 
the cats');
 'fat' & 'rat' & 'sleep' & 'cat'
Operadores
@@ ou @@@ tsvector casa (combina) com
tsquery? (ou vice-versa)
Exemplos:
SELECT to_tsquery('!(gato & rato)') @@ to_tsvector('O gato correu 
atrás do rato');
f
SELECT to_tsquery('(gato & rato)') @@ to_tsvector('O gato correu 
atrás do rato');
t
SELECT to_tsquery('(gato & navio)') @@ to_tsvector('O gato correu 
atrás do rato');
f
Operadores
@@ ou @@@ tsvector casa (combina) com
tsquery? (ou vice-versa)
Exemplos:
SELECT to_tsquery('(gato | navio)') @@ to_tsvector('O gato correu 
atrás do rato');
t
SELECT to_tsquery('gato | rato') @@ to_tsvector('rata');
t
Operadores
@@ ou @@@ tsvector casa com tsquery? (ou
vice-versa)
Operações possíveis:
● tsvector @@ tsquery
● tsquery @@ tsvector
● text @@ tsquery → equivalente a to_tsvector(x) @@ y
● text @@ text → equivalente a to_tsvector(x) @@
plainto_tsquery(y)
Operadores
!! Negação de uma tsquery
Exemplos:
SELECT !! to_tsquery('gato | rato') @@ to_tsvector('gatas');
 f
SELECT !! to_tsquery('gato | rato') @@ to_tsvector('abobrinha');
 t
Operadores
@> tsquery contém outra tsquery?
Exemplos:
SELECT to_tsquery('gato | rato | cão') @> to_tsquery('cão & 
rata');
 t
SELECT to_tsquery('gato | roda') @> to_tsquery('navio & macaco');
 f
Operadores
<@ tsquery está contida em outra tsquery?
Exemplos:
SELECT to_tsquery('moto & carro') <@ to_tsquery('moto | carro | 
ônibus');
 t
SELECT to_tsquery('moto | carro | ônibus') <@ to_tsquery('moto & 
carro');
 f
Base de Dados db_fts
● Foi criado exclusivamente para esta apresentação e possui
apenas uma tabela, a tb_post, cuja estrutura é:
● A tabela tem como função armazenar textos (artigos), cujos
campos são id, titulo, texto e tags. Um índice, pk_post,
para o campo id.
Coluna Tipo
id integer
titulo character varying(100)
texto text
tags character varying(200)
Índice: "pk_post" PRIMARY KEY, btree (id)
Consultas de Busca Textual
● Exemplo de consulta envolvendo concatenação de campos de
texto (VARCHAR e TEXT):
● A concatenação dos campos titulo, texto e tags foi
convertida para tsvector;
● Só foram exibidos os títulos dos registros, em que a concatenação
convertida casasse com a conversão da string “fruta” para texto
de consulta de busca textual.
SELECT titulo FROM tb_post WHERE 
to_tsvector(titulo||' '||texto||' '||tags) @@ to_tsquery('fruta');
   
 Ananás
 Limão
 Laranjeira
Consultas de Busca Textual
● E se eu quiser pesquisar uma frase?
● Ops... A string “presença humana” não é uma tsquery, tokens
soltos, sem os operadores “|” (OR) ou “&” (AND) não são
permitidos.
SELECT titulo FROM tb_post WHERE to_tsvector(titulo||' '||texto||' 
'||tags) @@ to_tsquery('presença humana'); 
ERROR:  syntax error in tsquery: "presença humana"
Consultas de Busca Textual
● Então, como fazer?:
● Explicitando o texto tsquery:
● Que tenha as palavras (normalizadas) “presença” e “humana”.
SELECT titulo FROM tb_post WHERE to_tsvector(titulo||' '||texto||' 
'||tags) @@ to_tsquery('presença & humana');
 Música
 Lobo
Consultas de Busca Textual
● … ou deixar que implicitamente a função plainto_tsquery
converta o texto plano passado para o formato tsquery:
● Vale lembrar que a função plainto_tsquery faz a conversão
utilizando a lógica AND (E).
SELECT titulo FROM tb_post WHERE to_tsvector(titulo||' '||texto||' 
'||tags) @@ plainto_tsquery('presença humana');
 
 Música
 Lobo
Consultas de Busca Textual
● to_tsquery: Requer previamente strings no formato tsquery e
então normaliza os tokens para lexemas;
● plainto_tsquery: Converte para o formato tsquery e normaliza
para lexemas;
● Sem stop words!
SELECT to_tsquery('presença & humana');
 'presenc' & 'human'
SELECT plainto_tsquery('presença humana');
   
 'presenc' & 'human'
Tabela com campo tsvector
● Até aqui os exemplos foram feitos utilizando a conversão em
tempo real de campos de texto concatenados para tsvector;
● Serve muito bem para exemplificar, porém, é mais custoso para o
servidor de banco de dados;
● Consequentemente mais demorada será a query:
EXPLAIN ANALYZE SELECT titulo FROM tb_post WHERE 
to_tsvector(titulo||' '||texto||' '||tags) @@ 
plainto_tsquery('presença humana');
. . .
 
 Total runtime: 12.031 ms
Tabela com campo tsvector
● Adição de um campo tsvector na tabela:
● Preenchendo o novo campo com a normalização da
concatenação dos campos titulo, texto e tags:
ALTER TABLE tb_post ADD COLUMN texto_vetor TSVECTOR;
UPDATE tb_post
SET texto_vetor = to_tsvector(titulo||' '||texto||' '||tags);
Tabela com campo tsvector
● Nova análise dos resultados, agora, com um campo tsvector:
● Uma melhora de desempenho muito evidente, mas tem como
ficar ainda melhor...
EXPLAIN ANALYZE 
SELECT titulo FROM tb_post 
WHERE texto_vetor @@ plainto_tsquery('presença humana');
. . .
 
 Total runtime: 0.559 ms
Índices GiST e GIN
● Há dois tipos de índices que podem ser usados para acelerar
buscas textuais: GiST e GIN;
● Não é obrigatório, mas seu uso beneficia o desempenho de
buscas textuais;
● Esses tipos de índices são aplicados a colunas dos tipos tsvector
ou tsquery;
● Há diferenças significantes entre os dois tipos de índices, então é
importante entender suas características.
Índices GiST e GIN
Sintaxe:
CREATE  INDEX  nome_indice  ON  nome_tabela  USING 
gist(nome_coluna);
Cria um índice GiST (Generalized Search Tree - Árvore de Busca
Generalizada)
CREATE  INDEX  nome_indice  ON  nome_tabela  USING 
gin(nome_coluna);
Cria um índice GIN (Generalized Inverted Index - Índice Invertido
Generalizado).
Índices GiST
● Um índice GiST tem perdas, o que significa que o índice pode produzir
falsos positivos e é necessário checar a linha atual da tabela para
eliminar tais falsos positivos (O PostgreSQL faz isso automaticamente
quando é preciso).
● Índices GiST têm perdas porque cada documento é representado no
índice por uma assinatura de largura fixa.
● Perdas fazem com que haja uma degradação de performance devido a
buscas desnecessárias nos registros de uma tabela que se tornam
falsos positivos.
Índices GiST
● Como o acesso aleatório a registros da tabela é lento, isso limita a
utilidade de índices GiST.
● A probabilidade de falsos positivos depende de vários fatores, em
particular o número de palavras únicas, então o uso de dicionários
para reduzir esse número é recomendado.
Índices GIN
● Um índice GIN não tem perdas para consultas padrão, mas sua
performance depende logaritmicamente do número de palavras
únicas.
● No entanto, índices GIN armazenam apenas as palavras
(lexemas) de valores tsvector, e não o peso de suas labels.
● Assim uma rechecagem de uma linha de uma tabela é necessária
quando usa uma consulta que envolve pesos.
GiST vs GIN: Qual Escolher?
Diferenças de performance:
● Buscas GIN são cerca de 3 (três) vezes mais rápidas do que
GiST;
● Índices GIN levam um tempo 3 (três) vezes maior para serem
construídos do que GiST;
● Índices GIN são moderadamente mais lentos para atualizar do
que os índices GiST, mas cerca de 10 (dez) vezes mais lento se o
suporte a fast-update for desabilitado;
● GIN são de 2 (duas) a 3 (três) vezes maiores do que índices GiST;
GiST vs GIN: Qual Escolher?
Resumindo:
● Índices GIN são melhores para dados estáticos porque as buscas
são mais rápidas;
● Para dados dinâmicos, os índices GiST são mais rápidos para
serem atualizados. Especificamente, índices GiST são muito bons
para dados dinâmicos e rápidos se palavras únicas (lexemas)
forem abaixo de 100.000 (cem mil), enquanto os índices GIN
lidarão melhor quando for acima disso, porém mais lentos para se
atualizarem;
GiST vs GIN: Qual Escolher?
● Vale lembrar que o tempo de construção de um índice GIN pode
frequentemente ser melhorado aumentando o parâmetro
maintenance_work_mem, porém isso não tem efeito para um índice
GiST;
● Particionamento de grandes coleções e o uso próprio de índices GiST
e GIN permite a implementação de buscas muito mais rápidas com
atualização online;
● Particionamento pode ser feito no nível da base de dados usando
herança de tabelas, ou pela distribuição de documentos sobre
servidores e coletando resultados de buscas usando o módulo dblink.
Sendo que esse último é possível por uso de funções de ranking em
informações locais apenas.
Criando um Índice no Campo tsvector (tipo)
● Criação do índice:
● Nova análise no campo de tipo tsvector com índice:
CREATE INDEX idx_texto_vetor ON tb_post USING GIN (texto_vetor);
EXPLAIN ANALYZE 
SELECT titulo FROM tb_post 
WHERE texto_vetor @@ plainto_tsquery('presença humana');
 
. . .
 Total runtime: 0.141 ms
Comparativo de Desempenho
Campo tsvector Atualizado Automaticamente
● Criação do gatilho:
● Ao inserir ou alterar registros, o trigger tg_texto_vetor aciona a
função built-in tsvector_update_trigger, no entanto essa
função é limitada... muito limitada!
● Não permite atribuir pesos através da função setweight.
CREATE TRIGGER tg_texto_vetor
BEFORE INSERT OR UPDATE ON tb_post
FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(texto_vetor,'pg_catalog.portuguese',titulo,
texto,tags);
Campo tsvector Atualizado Automaticamente
● Uma simples inserção de registro:
INSERT INTO tb_post (titulo, texto, tags) VALUES (
'Cidade de São Paulo',
'A cidade de São Paulo é a capital do Estado de mesmo nome e também 
a mais populosa do Brasil.',
'metrópole SP caos trânsito violência');
Campo tsvector Atualizado Automaticamente
● Consulta envolvendo busca textual:
● O que combina com “sp” no campo texto_vetor?
SELECT titulo FROM tb_post WHERE to_tsquery('sp') @@ texto_vetor;
 Cidade de São Paulo
Classificação de Resultados de Busca
● Classificar resultados é tentar medir o quanto um documento é
relevante para uma consulta em particular, de modo que quando
houver muitos "casamentos" (matches), os mais relevantes são
exibidos primeiro.
● No PostgreSQL há duas funções pré definidas de classificação,
que leva em conta léxicos, proximidade e estrutura da informação,
que é, considerar o quão frequentes os termos de uma consulta
aparecem em um documento, como estão próximos os termos, o
quão importante é a parte do documento que ocorre.
Classificação de Resultados de Busca
● Porém, o conceito de relevância é vago e varia especificamente
para uma aplicação. Aplicações diferentes podem pedir
informações adicionais para classificação, e.g.; data de
modificação do documento.
● As funções bult-in de classificação são apenas exemplos. Você
pode escrever suas próprias funções e / ou combinar seus
resultados com fatores adicionais para adequar às suas
necessidades específicas.
Classificação de Resultados de Busca
As duas funções de classificação disponíveis atualmente são:
● ts_rank([ weights float4[], ] vector tsvector,
                        query  tsquery  [,  normalization 
integer ]) returns float4
Classifica os vetores baseados na frequência da combinação de
seus lexemas.
Classificação de Resultados de Busca
● ts_rank_cd([  weights  float4[],  ]  vector 
tsvector, query tsquery [, normalization integer 
]) returns float4
Computa a classificação para densidade de correlacionamento*
(entre palavras) para um dado vetor de documento ou consulta.
Esta função requer informação posicional em sua entrada,
portanto não funcionará valores tsvector "stripped"**.
*Cover Density Ranking.
**Submetidos à função strip()
Classificação de Resultados de Busca
● Para ambas funções, os argumentos de pesos (weights) oferecem
a habilidade de fazer com que as buscas sejam feitas com pesos
especificados.
● A ordem crescente dos pesos é D, C, B, A.
● Existe uma função que define o peso de entrada de lexemas: a
função setweight;
● Não é possível combinar tsvector_update_trigger com
setweight.
Classificação de Resultados de Busca
● Uma limitação da função built-in tsvector_update_trigger é tratar
todas entradas de coluna de forma parecida.
● Para processar colunas diferentemente, por exemplo, atribuir
pesos diferentes para título, tags e o corpo de texto, é necessário
escrever uma função customizada.
Excluindo o gatilho criado anteriormente:
●
Atualizando toda a tabela com novos valores:
DROP TRIGGER tg_texto_vetor ON tb_post;
UPDATE tb_post SET texto_vetor =
setweight(to_tsvector(coalesce(titulo,'')),'A') ||
setweight(to_tsvector(coalesce(tags,'')),'B') ||
setweight(to_tsvector(coalesce(texto,'')),'C');
Classificação de Resultados de Busca
● Junto aos lexemas, além das posições, há os pesos:
● Criação da função customizada em PL/pgSQL:
SELECT texto_vetor FROM tb_post 
WHERE texto_vetor @@ to_tsquery('sp');
 'brasil':29C 'caos':7B 'capital':17C 'cidad':1A,11C 'estad':19C 
'metrópol':5B 'nom':22C 'paul':4A,14C 'popul':27C 'sp':6B 
'trânsit':8B 'violênc':9B 'é':15C
CREATE OR REPLACE FUNCTION fc_texto_vetor_upd() RETURNS trigger AS 
$$
begin
  new.fts :=
setweight(to_tsvector(coalesce(new.titulo,'')),'A') ||
setweight(to_tsvector(coalesce(new.tags,'')),'B') ||
setweight(to_tsvector(coalesce(new.texto,'')),'C');
  return new;
end
$$ LANGUAGE plpgsql;
Classificação de Resultados de Busca
Criação do gatilho:
Agora todas atualizações e inserções, fará com que o campo
texto_vetor tenha seu(s) valor(es) também com os pesos.
CREATE TRIGGER tg_upd_teste BEFORE INSERT OR UPDATE
    ON tb_post FOR EACH ROW EXECUTE PROCEDURE fc_texto_vetor_upd();
Destacando Resultados na Busca Textual
Função ts_headline
● Apresenta o(s) resultado (s) da busca, de modo a exibir a parte de
cada documento como está relacionada com a consulta.
● É muito comum, por exemplo, search engines mostrarem
fragmentos do documento com os termos de consulta marcados.
Sintaxe:
ts_headline([ config regconfig, ] document text, 
query tsquery [, options text ]) returns text
Destacando Resultados na Busca Textual
Função ts_headline
Exemplo:
No exemplo é demonstrado como destacar palavras relativas ao
termo pesquisado com HTML.
SELECT ts_headline(texto,to_tsquery('fruta'),'StartSel = <strong>, 
StopSel =</strong>') FROM tb_post
WHERE texto_vetor @@ to_tsquery('laranja');
<strong>fruto</strong> produzido pela laranjeira (Citrus × 
sinensis), uma árvore da família Rutaceae. A laranja é um 
<strong>fruto</strong>
DICIONÁRIOS
Dicionários
● Dicionários são usados para eliminar palavras que
não devem ser consideradas em uma busca (palavras
de parada / stop words) e normalizar palavras em
suas formas derivadas para uma base (lexema).
● Apesar de melhorar a qualidade de pesquisa,
normalização e remoção de stop words reduzem o
tamanho da representação do tsvector de um
documento, de forma a melhorar a performance.
● Nem sempre normalização tem um propósito
linguístico e geralmente depende da semântica da
aplicação.
Dicionários
Alguns exemplos de normalização:
● Linguística - Dicionários Ispell tentam reduzir palavras
de entrada para uma forma normalizada, dicionários
stemmer removem o fim de palavras;
● URLs podem ser normalizadas para fazer com que
diferentes combinem:
http://www.pgsql.ru/db/mw/index.html
http://www.pgsql.ru/db/mw/
http://www.pgsql.ru/db/../db/mw/index.html
Dicionários
Alguns exemplos de normalização:
● Nomes de cores podem ser substituídas por seus
valores hexadecimais, por exemplo: red, green, blue,
magenta -> FF0000, 00FF00, 0000FF, FF00FF
● Se indexar números, podemos remover alguns dígitos
fracionais para reduzir a faixa de possíveis números,
por exemplo:
3.14159265359, 3.1415926, 3.14 serão os mesmos
após normalização se apenas dois dígitos forem
mantidos após o ponto decimal.
Dicionários
Um dicionário é um programa que aceita um token
como entrada e retorna:
➔ Um vetor de lexemas se a entrada é conhecida para o
dicionário;
➔ Um vetor vazio se o dicionário conhece o token, mas
ele é uma palavra de parada;
➔ NULL se o dicionário não reconhece o token de
entrada.
Dicionários
● O PostgreSQL fornece dicionários predefinidos para
muitas linguagens. Há também templates predefinidos
que podem ser usados para criar novos dicionários
com parâmetros customizados.
● A regra geral para configurar uma lista de dicionários
é alocar primeiramente o mais restrito, mais
específico, então os mais gerais depois, fechando
com o dicionário mais geral, como um Snowball
stemmer ou simples, que reconhecem tudo.
● Cabe ao dicionário específico como tratar stop words.
Dicionários
● Por exemplo, os dicionários Ispell primeiro normalizam
palavras e depois buscam na lista de palavras de
parada, enquanto stemmers Snowball primeiro
verificam a lista de palavras de parada.
● A razão para o comportamento diferente é uma
tentativa para reduzir o "ruído".
● Para listar os dicionários de uma base de dados,
utlizamos o comando do psql:
dFd
Ou o comando SQL:
SELECT * FROM pg_ts_dict;
Dicionários
Importante!
● A maioria dos tipos de dicionários dependem de arquivos de
configuração, como os arquivos de stop words.
● Esses arquivos devem ser armazenados com o encoding UTF-8.
● Normalmente uma sessão lerá um arquivo de configuração de
dicionário uma única vez, quando for usado pela primeira vez
dentro da sessão.
● Se o arquivo de configuração for modificado e quer forçar as
sessões existentes a utilizar seu novo conteúdo, faça:
ALTER TEXT SEARCH DICTIONARY dicionário ...
Uma solução "dummy" que não mude nenhum valor :)
Dicionário Simples
● O template de dicionário simples converte cada token
de entrada em caixa baixa (letras minúsculas) e faz a
checagem em um arquivo de palavras de parada.
● Se esse token for achado no arquivo, será retornado
um vetor vazio, causando o descarte do token.
● Se o token não estiver nessa "lista negra", a forma em
letras minúsculas é retornada como um lexema
normalizado.
Dicionário Simples
Teste de lexização:
Diretório de buscas textuais:
Busca das palavras “foi” e “sim” no arquivo de palavras de parada em
português:
SELECT ts_lexize('public.dic_simples','SiM');
 {sim}
$ cd $SHAREDIR/tsearch_data
$ egrep 'foi|sim' portuguese.stop 
foi
Dicionário Simples
● Alternativamente, o dicionário pode ser configurado
para reportar o que não for palavra de parada como
desconhecida, permitindo serem passadas para o
próximo dicionário da lista.
Exemplo:
SELECT ts_lexize('public.dic_simples','foi');
 {}
SELECT ts_lexize('public.dic_simples','SiM');
 {sim}
Dicionário de Sinônimos
● Modelo de dicionário usado para criar dicionários que
substituem uma palavra com um sinônimo;
● Frases não são suportadas (usar o modelo thesaurus para
isso);
● Um dicionário de sinônimos pode ser usado para superar
problemas linguísticos, por exemplo, previnir que um
dicionário stemmer reduza a palavra "Paris" para "par";
● É suficiente ter uma linha Paris paris no dicionário de
sinônimo e colocá-lo antes do dicionário
portuguese_stem.
Dicionário de Sinônimos
A função ts_debug exibe o lexema da palavra “Paris”:
Criação da linha no arquivo de configuração do dicionário:
SELECT * FROM ts_debug('portuguese', 'Paris');
   alias   |   description   | token |   dictionaries    |   dictionary    | lexemes 
­­­­­­­­­­­+­­­­­­­­­­­­­­­­­+­­­­­­­+­­­­­­­­­­­­­­­­­­­+­­­­­­­­­­­­­­­­­+­­­­­­­­­
 asciiword | Word, all ASCII | Paris | {portuguese_stem} | portuguese_stem | {par}
$ echo 'Paris paris' > $SHAREDIR/tsearch_data/sinonimos.syn
Dicionário de Sinônimos
Criação do dicionário de sinônimos:
Adicionando o dicionário criado à configuração de busca textual
em português:
CREATE TEXT SEARCH DICTIONARY dic_sinonimos (
    TEMPLATE = synonym,
    SYNONYMS = sinonimos
);
ALTER TEXT SEARCH CONFIGURATION portuguese
    ALTER MAPPING FOR asciiword
    WITH dic_sinonimos, portuguese_stem;
Dicionário de Sinônimos
Novamente com a função ts_debug, mas agora o teste já conta
com o dicionário de sinônimos criado:
SELECT * FROM ts_debug('portuguese', 'Paris');
   alias   |   description   | token |          dictionaries           |  dictionary   | lexemes 
­­­­­­­­­­­+­­­­­­­­­­­­­­­­­+­­­­­­­+­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­+­­­­­­­­­­­­­­­+­­­­­­­­­
 asciiword | Word, all ASCII | Paris | {dic_sinonimos,portuguese_stem} | dic_sinonimos | {paris}
Dicionário Thesaurus
● Um dicionário thesaurus (às vezes abreviado como TZ) é uma
coleção de palavras que incluem informação sobre a relação
entre palavras e frases, por exemplo: termos mais amplos
(broader terms: BT), termos mais restritos (narrower terms: NT),
termos preferidos, termos não preferidos, termos relacionados,
etc.
● Basicamente substitui todos termos não preferidos por um termo
preferido e opcionalmente preserva os termos originais para
indexação, por exemplo.
Dicionário Thesaurus
● Na implementação atual do PostgreSQL do dicionário thesaurus é
uma extensão do dicionário de sinônimos com suporte a frase
adicionado.
● Esse tipo de dicionário requer um arquivo de configuração no
seguinte formato:
# comentário
palavra(s) de exemplo : palavra(s) indexada(s)
mais palavra(s) de exemplo : mais palavra(s) indexada(s)
...
O caractere ":" age como um delimitador entre uma frase e sua
substituição.
Dicionário Thesaurus
● Um dicionário thesaurus usa um subdicionário (que é especificado
na configuração de dicionário) para normalizar o texto de entrada
antes de checar por frases que combinem.
● É possível selecionar apenas um subdicionário. Um erro é
reportado se o subdicionário falha para reconhecer uma palavra.
Nesse caso, deve-se remover o uso da palavra ou ensinar o
dicionário sobre ela.
● Pode-se colocar um "*" no começo de uma palavra indexada para
pular a aplicação do subdicionário para ela, mas todas palavras
de exemplo devem ser conhecidas para o subdicionário.
Dicionário Thesaurus
● O dicionário thesaurus escolhe a combinação mais longa se há
múltiplas frases combinando com a entrada, e os laços são
quebrados usando a última definição.
● Stop words específicas reconhecidas pelo subdicionário não
podem ser especificadas ao invés de usar "?" para marcar a
localização onde qualquer stop word pode aparecer.
** Atenção **
Dicionários do tipo thesaurus são usados durante indexação, então qualquer
mudança em seus parâmetros requer reindexação, diferentemente de outros
tipos de dicionários.
Dicionário Thesaurus
Configuração Thesaurus
Para definir um novo dicionário thesaurus, use o modelo (template)
thesaurus, por exemplo:
●
Criação do dicionário thesaurus:
$ cp thesaurus_sample.ths pt_br_tz.ths
CREATE TEXT SEARCH DICTIONARY dic_pt_br_tz (
/* template */
TEMPLATE = thesaurus, 
/* arquivo de configuração (.ths). */
DictFile = pt_br_tz, 
/* subdicionário (português Snowball stemmer) */
 Dictionary = pg_catalog.portuguese_stem 
);
Dicionário Thesaurus
Agora é possível vincular o dicionário pt_br_tz para os tipos de
tokens desejados em uma configuração, por exemplo:
ALTER TEXT SEARCH CONFIGURATION portuguese
ALTER MAPPING FOR 
Asciiword,
Asciihword,
hword_asciipart
WITH 
dic_pt_br_tz,
portuguese_stem;
Dicionário Thesaurus
Testes:
SELECT to_tsvector('portuguese','cidade luz');
 
 'Paris':1 'cidad':2 'luz':3
SELECT to_tsvector('portuguese','jogar bola');
 'futebol':1
SELECT to_tsvector('portuguese','pasta de dente');
 'dentifríci':1
SELECT 
to_tsvector('portuguese','A cidade luz é a capital da França');
 'Paris':2 'capital':7 'cidad':3 'franc':9 'luz':4 'é':5
Dicionário Thesaurus
Se for necessário que uma palavra indexada não seja
lexemizada, deve ser colocado o asterisco na frente dela:
Um teste:
Ops! Não deu certo :(
O que deu errado? :|
$ echo 'sp : *São *Paulo' >> $SHAREDIR/tsearch_data/pt_br_tz.ths
SELECT to_tsvector('portuguese','sp');
 'sp':1
Dicionário Thesaurus
● É preciso fazer com que a(s) alteração(ões) no arquivo de
configuração do dicionário seja reconhecida.
● Dentro da sessão simule uma alteração na configuração do
dicionário:
Efetivamente não houve alteração alguma, mas o arquivo foi
relido :)
Funcionou!!! :D
ALTER TEXT SEARCH DICTIONARY dic_pt_br_tz ( DictFile = pt_br_tz );
SELECT to_tsvector('portuguese','sp');
 'Paulo':2 'São':1
Dicionário Ispell
● O template (modelo) de dicionário Ispell suporta dicionários morfológicos,
que pode normalizar muitas formas linguísticas diferentes de uma palavra
em um mesmo lexema.
● Um dicionário Ispell português pode combinar (casar) todas declinações e
conjugações de um termo de busca, como verbos irregulares, por exemplo.
● A distribuição padrão do PostgreSQL não inclui qualquer arquivo Ispell de
configuração.
● Dicionários para um grande número de idiomas estão disponíveis no Ispell.
● Formatos mais modernos de dicionários também são suportados: MySpell
(OO < 2.0.1) e Hunspell (OO >= 2.0.2). Uma vasta lista de dicionários está
disponível na Wiki do OpenOffice.
Dicionário Ispell
Instalação e Configuração
Instalação do pacote myspell-pt-br, que proverá os arquivos
necessários para o português brasileiro:
# aptitude install myspell­pt­br
Dicionário Ispell
Instalação e Configuração
Localizando os arquivos .aff e .dic, que são necessários para gerar os
arquivos .affix e .dict, respectivamente:
$ ACHADOS=`dpkg ­L myspell­pt­br | egrep '(dic|aff)$'`
$ for i in $ACHADOS; 
do 
if ! [ ­L $i ]; then 
echo $i; 
fi
done
/usr/share/hunspell/pt_BR.aff
/usr/share/hunspell/pt_BR.dic
Dicionário Ispell
Gerando os arquivos .dict e .affix, com codificação UTF-8:
$ iconv ­f latin1 ­t UTF­8 
/usr/share/hunspell/pt_BR.dic > $SHAREDIR/tsearch_data/pt_br.dict
$ iconv ­f latin1 ­t UTF­8 
/usr/share/hunspell/pt_BR.aff > $SHAREDIR/tsearch_data/pt_br.affix
Dicionário Ispell
Para criar um dicionário Ispell, use o template built-in e
especifique outros parâmetros:
CREATE TEXT SEARCH DICTIONARY dic_pt_br_ispell (
    TEMPLATE = ispell,
    DictFile = pt_br,
    AffFile = pt_br,
    StopWords = portuguese
);
Dicionário Ispell
● DictFile, AffFile e StopWords especificam os nomes,
respectivamente dos arquivos de dicionário, afixos e palavras de
parada.
● Dicionários Ispell normalmente reconhecem um conjunto limitado
de palavras, então eles devem ser seguidos por outro dicionário
mais amplo, como um dicionário Snowball, que reconhece tudo.
Dicionário Ispell
● Dicionários Ispell suportam divisão de palavras compostas, uma
característica muito útil.
Observação:
MySpell não suporte palavras compostas. Hunspell tem suporte
sofisticado para palavras compostas. Atualmente, o PostgreSQL
implementa apenas operações básicas do Hunspell para palavras
compostas.
Dicionário Ispell
Criação de uma nova configuração de busca textual, usando uma
pré existente como modelo:
Adicionando o dicionário Ispell criado à configuração:
ALTER TEXT SEARCH CONFIGURATION tsc_pt_br
    ALTER MAPPING FOR 
Asciiword,
asciihword, 
hword_asciipart,
word, 
Hword,
hword_part
        WITH 
dic_pt_br_ispell, 
portuguese_stem, 
simple;
CREATE TEXT SEARCH CONFIGURATION tsc_pt_br 
( COPY = pg_catalog.portuguese );
Dicionário Ispell
Testando (verbos irregulares):
SELECT to_tsvector('tsc_pt_br','caberia') @@ 
to_tsquery('tsc_pt_br','caibo');
 t
SELECT to_tsvector('tsc_pt_br','eu trouxe!!!');
 'trazer':2
Dicionário Snowball
● Este template de dicionário é baseado em um projeto de Martin
Porter, inventor do popular algoritmo de stemming para o inglês.
● Snowball hoje fornece algoritmo de stemming para muitos idiomas
(http://snowball.tartarus.org/). Cada algoritmo entendde como reduzir
formas variantes comum de palavras para uma base, ou stem, na
ortografia de seu idioma.
● Um dicionário Snowball requer um parâmetro de língua para
identificar que stemmer usar, e opcionalmente poder especificar
● um arquivo de palavras de parada que é uma lista de palavras para
eliminar. As listas de palavras de parada padrões do PostgreSQL
também são fornecidas pelo projeto Snownball.
Dicionário Snowball
Criação de um dicionário Snowball:
● Um dicionário Snowball reconhece tudo, simplificando uma
palavra ou não, então ele deve ser alocado ao final da lista de
dicionários.
● É inútil tê-lo antes que qualquer outro dicionário, pois um token
nunca passará por ele ao dicionário seguinte.
CREATE TEXT SEARCH DICTIONARY portuguese_stem (
    TEMPLATE = snowball,
    Language = portuguese,
    StopWords = portuguese
);
Configuração de Busca Textual
● Especifica todas opções necessárias para transformar um
documento em um tsvector: o parser para quebrar texto em
tokens e os dicionários para transformar cada token em um
lexema.
● Toda chamada a funções como to_tsvector e to_tsquery
necessita de uma configuração para fazer seu processamento.
● O parâmetro de configuração default_text_search_config
especifca o nome da configuração padrão, que será é utilizada
por funções de buscas textuais se o padrão relativo à
configuração de busca textual for omitido.
Configuração de Busca Textual
● Essa configuração pode ser configurada no postgresql.conf ou em
uma sessão individual utilizando o comando SET.
● Muitas configurações de busca textual pré definidas estão
disponíveis, e é possível criar uma customizada facilmente.
● Para facilitar o gerenciamento de objetos de busca textual, um
conjunto de comandos SQL está disponível e e há vários
comandos do psql que exibem informações sobre objetos de
busca textual.
Configuração de Busca Textual
Como exemplo vamos criar uma configuração chamada tsc_pg,
começando pela duplicação da configuração português built-in:
Vamos usar uma lista de sinônimos específica do PostgreSQL
($SHAREDIR/tsearch_data/pg_dict.syn), cujo conteúdo será:
postgres    pg
pgsql       pg
postgresql  pg
CREATE TEXT SEARCH CONFIGURATION public.tsc_pg
(COPY = pg_catalog.portuguese);
Configuração de Busca Textual
Definiremos o dicionário de sinônimos como este:
Agora registraremos o dicionário Ispell portuguese_ispell, que tem
seus próprios arquivos de configuração:
CREATE TEXT SEARCH DICTIONARY dic_pg (
    TEMPLATE = synonym,
    SYNONYMS = pg_dict
);
CREATE TEXT SEARCH DICTIONARY dic_portuguese_ispell (
    TEMPLATE = ispell,
    DictFile = pt_br,
    AffFile = pt_br,
    StopWords = portuguese
);
Configuração de Busca Textual
Configuração dos mapeamentos de palavras na configuração
tsc_pg:
ALTER TEXT SEARCH CONFIGURATION tsc_pg
    ALTER MAPPING FOR asciiword,
asciihword,
hword_asciipart,
word, 
hword, 
hword_part
    WITH dic_pg,
dic_portuguese_ispell, 
portuguese_stem;
Configuração de Busca Textual
Testando:
SELECT ts_debug ('public.tsc_pg','postgresql');
(asciiword,"Word, all ASCII",postgresql,
"{dic_pg,dic_portuguese_ispell,portuguese_stem}",dic_pg,{pg})
SELECT ts_debug ('public.tsc_pg','pgsql');
 (asciiword,"Word, all ASCII",pgsql,
"{dic_pg,dic_portuguese_ispell,portuguese_stem}",dic_pg,{pg})
SELECT ts_debug ('public.tsc_pg','postgres');
 (asciiword,"Word, all ASCII",postgres,
"{dic_pg,dic_portuguese_ispell,portuguese_stem}",dic_pg,{pg})
Configuração de Busca Textual
● Para listar as configurações existentes podemos fazer das seguintes
maneiras:
- via psql: dF
- via SQL: SELECT cfgname FROM pg_ts_config;
● Configurando a sessão para usar a nova configuração, que foi criada
no schema public:
Conferindo:
SET default_text_search_config = 'public.tsc_pg';
SHOW default_text_search_config;
 public.tsc_pg
Módulo unaccent
● É um módulo contrib que implementa um dicionário de busca
textual que remove acentos de lexemas.
● É um dicionário de filtragem, o que significa que sua saída é
sempre passada para o próximo dicionário (se for o caso), ao
contrário do comportamento normal de dicionários. Isso permite
processamento de busca textual sem considerar acentos.
● A implementação atual do unaccent não pode ser usada como um
dicionário de normalização para o dicionário thesaurus.
Módulo unaccent
Configuração
● RULES é o nome do arquivo que contém a lista de regras de
tradução.
● Esse arquivo deve estar armazenado em
$SHAREDIR/tsearch_data/, cujo nome deve ter a extensão
.rules (tal extensão não deve ser incluída no parâmetro RULES).
Módulo unaccent
Configuração
● O arquivo de regras deve ter o seguinte formato:
      À        A
    Á        A
    Â        A
    Ã        A
    Ä        A
    Å        A
    Æ        A
Módulo unaccent
● Cada linha representa um par, consistindo de um caractere com
acento seguido que será traduzido pelo seguinte que é sem
acento.
● Um exemplo mais completo, que é diretamente útil para a maioria
dos idiomas europeus, pode ser encontrado no arquivo
unaccent.rules, que é instalado do diretório
$SHAREDIR/tsearch_data/ quando o módulo é instalado.
● Para instalar o módulo acesse a base de dados que deseja nela
trabalhar com o dicionário unaccent e dê o comando:
CREATE EXTENSION unaccent;
Módulo unaccent
Uso
● Ao instalar a extensão unaccent cria-se um template de busca
textual unaccent e um dicionário unaccent baseados nela.
● O dicionário unaccent tem o parâmetro padrão de configuração
RULES='unaccent', faz com que seja imediatamente utilizável
pelo arquivo unaccent.rules.
● Se preferir, pode alterar o parâmetro, por exemplo:
...ou criar novos dicionários baseados no template.
ALTER TEXT SEARCH DICTIONARY unaccent (RULES='minhas_regras');
Módulo unaccent
Testando:
SELECT ts_lexize('unaccent','Armação');
 {Armacao}
Módulo unaccent
Um exemplo de como inserir um dicionário unaccent em uma
configuração de busca textual:
CREATE TEXT SEARCH CONFIGURATION tsc_pt_unaccent
( COPY = portuguese );
Módulo unaccent
ALTER TEXT SEARCH CONFIGURATION tsc_pt_unaccent
    ALTER MAPPING FOR asciiword,
Asciihword,
hword_asciipart,
                   word, 
hword, 
hword_part
WITH 
dic_pt_br_ispell, 
unaccent, 
portuguese_stem, 
simple;
Observação:
Na função ts_lexize, seu primeiro parâmetro é um dicionário de
busca textual e não uma configuração de busca textual.
Módulo unaccent
Testes:
SELECT to_tsvector('tsc_pt_unaccent','Hotéis do Mar');
 'hotel':1 'mar':3
SELECT to_tsvector('tsc_pt_unaccent','Hotéis do Mar') @@ 
to_tsquery('tsc_pt_unaccent','Hotel');
 t
SELECT ts_headline('tsc_pt_unaccent','Hotéis do Mar',
to_tsquery('tsc_pt_unaccent','Hotel'));
 <b>Hotéis</b> do Mar
Módulo unaccent
Função unaccent
● Remove acentos de uma dada string.
● Basicamente, é um invólucro (wrapper) que envolve o dicionário
unaccent, mas pode ser usada fora do contexto de busca
textual.
unaccent([dicionário, ] string) returns text
Exemplo:
SELECT unaccent('unaccent', 'Hotéis');
 Hoteis
Dúvidas???
Muito Obrigado!!! :D
Juliano Atanazio
juliano777@gmail.com

Contenu connexe

Tendances

Running Natural Language Queries on MongoDB
Running Natural Language Queries on MongoDBRunning Natural Language Queries on MongoDB
Running Natural Language Queries on MongoDBMongoDB
 
ELK: Moose-ively scaling your log system
ELK: Moose-ively scaling your log systemELK: Moose-ively scaling your log system
ELK: Moose-ively scaling your log systemAvleen Vig
 
Introduction to Elasticsearch with basics of Lucene
Introduction to Elasticsearch with basics of LuceneIntroduction to Elasticsearch with basics of Lucene
Introduction to Elasticsearch with basics of LuceneRahul Jain
 
엘라스틱 서치 세미나
엘라스틱 서치 세미나엘라스틱 서치 세미나
엘라스틱 서치 세미나종현 김
 
Graphql presentation
Graphql presentationGraphql presentation
Graphql presentationVibhor Grover
 
Elasticsearch in Netflix
Elasticsearch in NetflixElasticsearch in Netflix
Elasticsearch in NetflixDanny Yuan
 
Curso Java Básico - Aula 01
Curso Java Básico - Aula 01Curso Java Básico - Aula 01
Curso Java Básico - Aula 01Natanael Fonseca
 
[Meetup] a successful migration from elastic search to clickhouse
[Meetup] a successful migration from elastic search to clickhouse[Meetup] a successful migration from elastic search to clickhouse
[Meetup] a successful migration from elastic search to clickhouseVianney FOUCAULT
 
Curso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicosCurso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicosTiago Antônio da Silva
 
HTML - Listas, Estilos, Tabelas, Div, Span, Formulário
HTML -  Listas, Estilos, Tabelas, Div, Span, FormulárioHTML -  Listas, Estilos, Tabelas, Div, Span, Formulário
HTML - Listas, Estilos, Tabelas, Div, Span, FormulárioArthur Emanuel
 
Introdução básica ao JavaScript
Introdução básica ao JavaScriptIntrodução básica ao JavaScript
Introdução básica ao JavaScriptCarlos Eduardo Kadu
 
JavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosJavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosEduardo Mendes
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]GDSC UofT Mississauga
 
Aula 01 - JavaScript: Introdução
Aula 01 - JavaScript: IntroduçãoAula 01 - JavaScript: Introdução
Aula 01 - JavaScript: IntroduçãoJessyka Lage
 

Tendances (20)

Running Natural Language Queries on MongoDB
Running Natural Language Queries on MongoDBRunning Natural Language Queries on MongoDB
Running Natural Language Queries on MongoDB
 
ELK: Moose-ively scaling your log system
ELK: Moose-ively scaling your log systemELK: Moose-ively scaling your log system
ELK: Moose-ively scaling your log system
 
Aula03 - JavaScript
Aula03 - JavaScriptAula03 - JavaScript
Aula03 - JavaScript
 
Introduction to Elasticsearch with basics of Lucene
Introduction to Elasticsearch with basics of LuceneIntroduction to Elasticsearch with basics of Lucene
Introduction to Elasticsearch with basics of Lucene
 
Intro to JSON
Intro to JSONIntro to JSON
Intro to JSON
 
엘라스틱 서치 세미나
엘라스틱 서치 세미나엘라스틱 서치 세미나
엘라스틱 서치 세미나
 
Graphql presentation
Graphql presentationGraphql presentation
Graphql presentation
 
PostgreSQL
PostgreSQLPostgreSQL
PostgreSQL
 
Elasticsearch in Netflix
Elasticsearch in NetflixElasticsearch in Netflix
Elasticsearch in Netflix
 
Curso Java Básico - Aula 01
Curso Java Básico - Aula 01Curso Java Básico - Aula 01
Curso Java Básico - Aula 01
 
[Meetup] a successful migration from elastic search to clickhouse
[Meetup] a successful migration from elastic search to clickhouse[Meetup] a successful migration from elastic search to clickhouse
[Meetup] a successful migration from elastic search to clickhouse
 
Curso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicosCurso CSS 3 - Aula Introdutória com conceitos básicos
Curso CSS 3 - Aula Introdutória com conceitos básicos
 
HTML - Listas, Estilos, Tabelas, Div, Span, Formulário
HTML -  Listas, Estilos, Tabelas, Div, Span, FormulárioHTML -  Listas, Estilos, Tabelas, Div, Span, Formulário
HTML - Listas, Estilos, Tabelas, Div, Span, Formulário
 
Elasticsearch
ElasticsearchElasticsearch
Elasticsearch
 
Gerência de Requisitos
Gerência de RequisitosGerência de Requisitos
Gerência de Requisitos
 
Introdução básica ao JavaScript
Introdução básica ao JavaScriptIntrodução básica ao JavaScript
Introdução básica ao JavaScript
 
JavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosJavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a Objetos
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
Estrutura de dados - Filas
Estrutura de dados - FilasEstrutura de dados - Filas
Estrutura de dados - Filas
 
Aula 01 - JavaScript: Introdução
Aula 01 - JavaScript: IntroduçãoAula 01 - JavaScript: Introdução
Aula 01 - JavaScript: Introdução
 

En vedette

Curso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos ComandosCurso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos ComandosMarcos Thomaz
 
Criação de log de ações através do banco - PostgreSQL
Criação de log de ações através do banco - PostgreSQLCriação de log de ações através do banco - PostgreSQL
Criação de log de ações através do banco - PostgreSQLMarcos Thomaz
 
A literacia da informação nas bibliotecas escolares: como descrever e pesquis...
A literacia da informação nas bibliotecas escolares: como descrever e pesquis...A literacia da informação nas bibliotecas escolares: como descrever e pesquis...
A literacia da informação nas bibliotecas escolares: como descrever e pesquis...Cristiana Freitas
 
Política de Indexação de Fotografias
Política de Indexação de FotografiasPolítica de Indexação de Fotografias
Política de Indexação de FotografiasAlanna Gianin
 
Manual PLSQL
Manual PLSQLManual PLSQL
Manual PLSQLUMSA
 
MANUAL COMPLETO DE SQL
MANUAL COMPLETO DE SQLMANUAL COMPLETO DE SQL
MANUAL COMPLETO DE SQLEdgar Sandoval
 
Banco de dados exercícios resolvidos
Banco de dados exercícios resolvidosBanco de dados exercícios resolvidos
Banco de dados exercícios resolvidosGleydson Sousa
 
key to improving core competitive capacity 4 enterprise
key to improving core competitive capacity 4 enterprisekey to improving core competitive capacity 4 enterprise
key to improving core competitive capacity 4 enterpriseTrung Ngoc
 
Ch11 z5e solutions
Ch11 z5e solutionsCh11 z5e solutions
Ch11 z5e solutionsblachman
 
Web Security Programming I I
Web  Security  Programming  I IWeb  Security  Programming  I I
Web Security Programming I IPavu Jas
 
Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...
Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...
Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...Michael Kirst-Neshva
 
Happy Paths: UX Tested, Unicorn Approved -- Katie Swindler
Happy Paths: UX Tested, Unicorn Approved -- Katie SwindlerHappy Paths: UX Tested, Unicorn Approved -- Katie Swindler
Happy Paths: UX Tested, Unicorn Approved -- Katie SwindlerWIADchicago
 
EGFR vIII as a targeting agent for BNCT
EGFR vIII as a targeting agent for BNCTEGFR vIII as a targeting agent for BNCT
EGFR vIII as a targeting agent for BNCTkent.riley
 
CHN-006-物流架構與定位
CHN-006-物流架構與定位CHN-006-物流架構與定位
CHN-006-物流架構與定位handbook
 

En vedette (20)

Curso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos ComandosCurso de PostgreSQL: Um pouco Além dos Comandos
Curso de PostgreSQL: Um pouco Além dos Comandos
 
Criação de log de ações através do banco - PostgreSQL
Criação de log de ações através do banco - PostgreSQLCriação de log de ações através do banco - PostgreSQL
Criação de log de ações através do banco - PostgreSQL
 
Indexacao margarida frois
Indexacao margarida froisIndexacao margarida frois
Indexacao margarida frois
 
Procurar descobrir e usar informação
Procurar descobrir e usar informaçãoProcurar descobrir e usar informação
Procurar descobrir e usar informação
 
A literacia da informação nas bibliotecas escolares: como descrever e pesquis...
A literacia da informação nas bibliotecas escolares: como descrever e pesquis...A literacia da informação nas bibliotecas escolares: como descrever e pesquis...
A literacia da informação nas bibliotecas escolares: como descrever e pesquis...
 
Política de Indexação de Fotografias
Política de Indexação de FotografiasPolítica de Indexação de Fotografias
Política de Indexação de Fotografias
 
Manual PLSQL
Manual PLSQLManual PLSQL
Manual PLSQL
 
Exercícios PL/SQL
Exercícios PL/SQLExercícios PL/SQL
Exercícios PL/SQL
 
MANUAL COMPLETO DE SQL
MANUAL COMPLETO DE SQLMANUAL COMPLETO DE SQL
MANUAL COMPLETO DE SQL
 
Banco de dados exercícios resolvidos
Banco de dados exercícios resolvidosBanco de dados exercícios resolvidos
Banco de dados exercícios resolvidos
 
Full Text Search In PostgreSQL
Full Text Search In PostgreSQLFull Text Search In PostgreSQL
Full Text Search In PostgreSQL
 
key to improving core competitive capacity 4 enterprise
key to improving core competitive capacity 4 enterprisekey to improving core competitive capacity 4 enterprise
key to improving core competitive capacity 4 enterprise
 
Ch11 z5e solutions
Ch11 z5e solutionsCh11 z5e solutions
Ch11 z5e solutions
 
Web Security Programming I I
Web  Security  Programming  I IWeb  Security  Programming  I I
Web Security Programming I I
 
Mig gig first draft
Mig gig first draftMig gig first draft
Mig gig first draft
 
Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...
Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...
Hybrid cloud iaa-s_office-365-azure_sharepoint-konferenz-wien-2013_ankbs_mich...
 
Happy Paths: UX Tested, Unicorn Approved -- Katie Swindler
Happy Paths: UX Tested, Unicorn Approved -- Katie SwindlerHappy Paths: UX Tested, Unicorn Approved -- Katie Swindler
Happy Paths: UX Tested, Unicorn Approved -- Katie Swindler
 
EGFR vIII as a targeting agent for BNCT
EGFR vIII as a targeting agent for BNCTEGFR vIII as a targeting agent for BNCT
EGFR vIII as a targeting agent for BNCT
 
Versos
VersosVersos
Versos
 
CHN-006-物流架構與定位
CHN-006-物流架構與定位CHN-006-物流架構與定位
CHN-006-物流架構與定位
 

Similaire à Busca Textual no PostgreSQL (Full Text Search

Dicas importantes do postgre sql pg admin
Dicas importantes do postgre sql pg adminDicas importantes do postgre sql pg admin
Dicas importantes do postgre sql pg adminEp Forp
 
Solisc2009 Migrando de Oracle para Postgresql
Solisc2009 Migrando de Oracle para PostgresqlSolisc2009 Migrando de Oracle para Postgresql
Solisc2009 Migrando de Oracle para PostgresqlLeonardo Medeiros Martins
 
Comandos gerais do PHP
Comandos gerais do PHPComandos gerais do PHP
Comandos gerais do PHPPaulo Dayvson
 
Linguagem de Programação PERL
Linguagem de Programação PERLLinguagem de Programação PERL
Linguagem de Programação PERLTiago R. Sampaio
 
Delphi Conference 2011 - Desmistificando as Expressões Regulares
Delphi Conference 2011 - Desmistificando as Expressões RegularesDelphi Conference 2011 - Desmistificando as Expressões Regulares
Delphi Conference 2011 - Desmistificando as Expressões RegularesMario Guedes
 
Algoritmo estruturado
Algoritmo estruturadoAlgoritmo estruturado
Algoritmo estruturadodasko
 
Aprendendo PHP.pdf
Aprendendo PHP.pdfAprendendo PHP.pdf
Aprendendo PHP.pdfssuserad6350
 
Otimizando suas querys no postgreSQL
Otimizando suas querys no postgreSQLOtimizando suas querys no postgreSQL
Otimizando suas querys no postgreSQLJean Pierre Monteiro
 
Oracle para PostgreSQL: Conseguir migrar e não parar UTI
Oracle para PostgreSQL: Conseguir migrar e não parar UTIOracle para PostgreSQL: Conseguir migrar e não parar UTI
Oracle para PostgreSQL: Conseguir migrar e não parar UTIFernando Ike
 
Conceitos base de programação - parte 1
Conceitos base de programação - parte 1Conceitos base de programação - parte 1
Conceitos base de programação - parte 1João Piedade
 
Functional programming feat. Swift (Portuguese)
Functional programming feat. Swift (Portuguese)Functional programming feat. Swift (Portuguese)
Functional programming feat. Swift (Portuguese)FrankKair1
 

Similaire à Busca Textual no PostgreSQL (Full Text Search (20)

JavaCC
JavaCCJavaCC
JavaCC
 
Dicas importantes do postgre sql pg admin
Dicas importantes do postgre sql pg adminDicas importantes do postgre sql pg admin
Dicas importantes do postgre sql pg admin
 
teste
testeteste
teste
 
apostila-expressoes-regulares.pdf
apostila-expressoes-regulares.pdfapostila-expressoes-regulares.pdf
apostila-expressoes-regulares.pdf
 
Solisc2009 Migrando de Oracle para Postgresql
Solisc2009 Migrando de Oracle para PostgresqlSolisc2009 Migrando de Oracle para Postgresql
Solisc2009 Migrando de Oracle para Postgresql
 
Por que PostgreSQL?
Por que PostgreSQL?Por que PostgreSQL?
Por que PostgreSQL?
 
Comandos gerais do PHP
Comandos gerais do PHPComandos gerais do PHP
Comandos gerais do PHP
 
Linguagens de programação
Linguagens de programaçãoLinguagens de programação
Linguagens de programação
 
Compiladores
CompiladoresCompiladores
Compiladores
 
Linguagem de Programação PERL
Linguagem de Programação PERLLinguagem de Programação PERL
Linguagem de Programação PERL
 
Linguagem C - Funções
Linguagem C - FunçõesLinguagem C - Funções
Linguagem C - Funções
 
Delphi Conference 2011 - Desmistificando as Expressões Regulares
Delphi Conference 2011 - Desmistificando as Expressões RegularesDelphi Conference 2011 - Desmistificando as Expressões Regulares
Delphi Conference 2011 - Desmistificando as Expressões Regulares
 
Algoritmo estruturado
Algoritmo estruturadoAlgoritmo estruturado
Algoritmo estruturado
 
Aula4
Aula4Aula4
Aula4
 
Aprendendo PHP.pdf
Aprendendo PHP.pdfAprendendo PHP.pdf
Aprendendo PHP.pdf
 
Otimizando suas querys no postgreSQL
Otimizando suas querys no postgreSQLOtimizando suas querys no postgreSQL
Otimizando suas querys no postgreSQL
 
Oracle para PostgreSQL: Conseguir migrar e não parar UTI
Oracle para PostgreSQL: Conseguir migrar e não parar UTIOracle para PostgreSQL: Conseguir migrar e não parar UTI
Oracle para PostgreSQL: Conseguir migrar e não parar UTI
 
Conceitos base de programação - parte 1
Conceitos base de programação - parte 1Conceitos base de programação - parte 1
Conceitos base de programação - parte 1
 
Functional programming feat. Swift (Portuguese)
Functional programming feat. Swift (Portuguese)Functional programming feat. Swift (Portuguese)
Functional programming feat. Swift (Portuguese)
 
XML Schema (2002)
XML Schema (2002)XML Schema (2002)
XML Schema (2002)
 

Plus de Juliano Atanazio

PL/Python: Programando em Python no PostgreSQL
PL/Python: Programando em Python no PostgreSQLPL/Python: Programando em Python no PostgreSQL
PL/Python: Programando em Python no PostgreSQLJuliano Atanazio
 
Por que Python? Vamos Conhecer? Vamos Aprender?
Por que Python? Vamos Conhecer? Vamos Aprender?Por que Python? Vamos Conhecer? Vamos Aprender?
Por que Python? Vamos Conhecer? Vamos Aprender?Juliano Atanazio
 
PostgreSQL: How to Store Passwords Safely
PostgreSQL: How to Store Passwords SafelyPostgreSQL: How to Store Passwords Safely
PostgreSQL: How to Store Passwords SafelyJuliano Atanazio
 
Neutralizing SQL Injection in PostgreSQL
Neutralizing SQL Injection in PostgreSQLNeutralizing SQL Injection in PostgreSQL
Neutralizing SQL Injection in PostgreSQLJuliano Atanazio
 
Postgresql + Python = Power!
Postgresql + Python = Power!Postgresql + Python = Power!
Postgresql + Python = Power!Juliano Atanazio
 
Boas praticas em um Projeto de Banco de Dados
Boas praticas em um Projeto de Banco de DadosBoas praticas em um Projeto de Banco de Dados
Boas praticas em um Projeto de Banco de DadosJuliano Atanazio
 
Gerenciamento de Backups PostgreSQL com pgbarman
Gerenciamento de Backups PostgreSQL com pgbarmanGerenciamento de Backups PostgreSQL com pgbarman
Gerenciamento de Backups PostgreSQL com pgbarmanJuliano Atanazio
 

Plus de Juliano Atanazio (8)

PL/Python: Programando em Python no PostgreSQL
PL/Python: Programando em Python no PostgreSQLPL/Python: Programando em Python no PostgreSQL
PL/Python: Programando em Python no PostgreSQL
 
Por que Python? Vamos Conhecer? Vamos Aprender?
Por que Python? Vamos Conhecer? Vamos Aprender?Por que Python? Vamos Conhecer? Vamos Aprender?
Por que Python? Vamos Conhecer? Vamos Aprender?
 
Por que FreeBSD?
Por que FreeBSD?Por que FreeBSD?
Por que FreeBSD?
 
PostgreSQL: How to Store Passwords Safely
PostgreSQL: How to Store Passwords SafelyPostgreSQL: How to Store Passwords Safely
PostgreSQL: How to Store Passwords Safely
 
Neutralizing SQL Injection in PostgreSQL
Neutralizing SQL Injection in PostgreSQLNeutralizing SQL Injection in PostgreSQL
Neutralizing SQL Injection in PostgreSQL
 
Postgresql + Python = Power!
Postgresql + Python = Power!Postgresql + Python = Power!
Postgresql + Python = Power!
 
Boas praticas em um Projeto de Banco de Dados
Boas praticas em um Projeto de Banco de DadosBoas praticas em um Projeto de Banco de Dados
Boas praticas em um Projeto de Banco de Dados
 
Gerenciamento de Backups PostgreSQL com pgbarman
Gerenciamento de Backups PostgreSQL com pgbarmanGerenciamento de Backups PostgreSQL com pgbarman
Gerenciamento de Backups PostgreSQL com pgbarman
 

Busca Textual no PostgreSQL (Full Text Search

  • 1. Full Text Search - Busca Textual no PostgreSQL Palestrante: Juliano Atanazio
  • 2. O que é? Para que serve? ● Full Text Search / Text Search / Busca Textual: é um mecanismo que possibilita identificar documentos em linguagem natural que casem com uma consulta e opcionalmente ordená-los por relevância. ● O uso mais comum de busca é encontrar todos documentos que contém termos de uma consulta e retorná-los conforme sua semelhança com essa consulta.
  • 3. Operadores ~, ~*, LIKE, and ILIKE Por que NÃO? ● Não há suporte linguístico (mesmo para inglês); ● Expressões regulares não são suficientes, pois é difícil lidar com derivações de palavras; ● Não tem ordem (relevância) de resultados de busca, o que os faz ineficazes quando milhares de documentos que casem são encontrados; ● Tendência a lentidão, por não haver suporte a índice, então eles têm que processar todos documentos por cada busca.
  • 4. Termos ● Documento É a unidade de busca em um sistema de busca textual, por exemplo: um artigo de revista ou uma mensagem de e-mail. Para buscas no PostgreSQL, um documento é normalmente um campo de texto em uma linha de uma tabela, ou possivelmente uma combinação (concatenação) de campos. Resumindo: documento em buscas textuais é um texto.
  • 5. Termos SELECT titulo||' '||texto||' '||texto FROM tb_post WHERE id=1; Laranjeira A laranja é o fruto produzido pela laranjeira (Citrus × sinensis), uma árvore da família Rutaceae. A  laranja é um fruto híbrido, criado na antiguidade a partir do cruzamento da cimboa com a tangerina. O sabor da  laranja varia do doce ao levemente ácido. Frequentemente, esta fruta é descascada e comida ao natural, ou  espremida para obter sumo. As pevides (pequenos caroços duros) são habitualmente removidas, embora possam ser  usadas em algumas receitas. A casca exterior pode ser usada também em diversos pratos culinários, como  ornamento, ou mesmo para dar algum sabor. A camada branca entre a casca e as gomas, de dimensão variável,  raramente é utilizada, apesar de ter um sabor levemente doce. É recomendada para "quebrar" o sabor ácido da  laranja na boca, após terminar de consumir o fruto. ● Documento Exemplo: A partir da consulta extraiu-se o documento.
  • 6. Termos ● Token Tokens são as palavras em um documento, que podem variar seus tipos como números, palavras, palavras complexas e endereços de e-mail. Exemplo: O documento foi convertido em tokens. SELECT 'O rato foi pego pela gata preta, pelo gato branco e pelo cachorro  de pêlos lisos'::tsvector; 'O' 'branco' 'cachorro' 'de' 'e' 'foi' 'gata' 'gato' 'lisos' 'pego' 'pela' 'pelo' 'preta,' 'pêlos' 'rato'
  • 7. SELECT to_tsvector('gatas'); 'gat':1 Termos ● Lexema Palavra ou parte da palavra que serve de base ao sentido por ela. Similar ao conceito de radical em gramática. Exemplos: SELECT to_tsvector('gato'); 'gat':1
  • 8. Termos ● Stop Words / Palavras de Parada São palavras que podem ser consideradas irrelevantes para o conjunto de resultados a ser exibido em uma busca realizada em um search engine. Exemplos: Artigos: o, a, os, as, um, uma, uns, umas Conjunções: e, nem, mas, já, mas, ou, que, se Crase: à Preposições: a, com, como, de, em, para, por, sem Pronomes: eu, nós, tu, vós, ele, eles, ela, elas, seu, teu, meu, no, na, nos, nas, quem, que, qual
  • 9. Termos Stop Words / Palavras de Parada ● O postgres lê o arquivo de palavras de parada que está em $SHAREDIR/tsearch_data/ cuja extensão desse arquivo é .stop. Seu conteúdo é de apenas stop words. ● $SHAREDIR pode variar dependendo da instalação do PostgreSQL. Por padrão é o diretório share da instalação. ● Para o idioma português o arquivo é $SHAREDIR/tsearch_data/portuguese.stop ● Para obter o valor de $SHAREDIR, dê o comando no shell: $ pg_config ­­sharedir
  • 10. SELECT 'O rato foi pego pela gata preta, pelo gato branco e  pelo cachorro de pêlos lisos'::tsvector; 'O' 'branco' 'cachorro' 'de' 'e' 'foi' 'gata' 'gato' 'lisos' 'pego' 'pela' 'pelo' 'preta,' 'pêlos' 'rato' Pré Processamento Documento LexemasTokens 1 2 Exemplos: 1) 2) Cadê as stop words no 2??? SELECT to_tsvector('O rato foi pego pela gata preta, pelo gato branco e pelo cachorro de pêlos liso'); 'branc':10 'cachorr':13 'gat':6,9 'lis':16 'peg':4 'pret':7 'pêl':15  'rat':2
  • 11. Ajustando a Configuração de Busca Textual ● A funcionalidades de busca textual é controlada por configurações de busca textual. O PostgreSQL vem com configurações pré definidas para muitos idiomas. ● Para listar todas as configurações disponíveis, no psql, dê o comando: ● Para exibir qual é a configuração que está em uso na sessão: ● Essa configuração pode ser mudada para todo o cluster no postgresql.conf, bastando apenas um reload no serviço ou mesmo para a sessão atual: dF SHOW default_text_search_config; pg_catalog.english SET default_text_search_config = 'pg_catalog.portuguese';
  • 12. Tipos e Respectivas Funções SELECT 'O carro correu, correu e venceu a corrida facilmente,  ultrapassando o último carro a 15 min do final'::tsvector; '15' 'O' 'a' 'carro' 'correu' 'correu,' 'corrida' 'do' 'e' 'facilmente,'  'final' 'min' 'o' 'ultrapassando' 'venceu' 'último' Tipo tsvector ● Vetor de lexemas e posições; ● Representa um documento em uma forma otimizada para buscas de texto; ● Seu valor é uma lista ordenada de lexemas distintos; ● Ordena, elimina duplicações automaticamente; ● Representa um documento de forma compacta;
  • 13. Tipos e Respectivas Funções Tipo tsvector ● Opcionalmente, posições (em números inteiros) podem ser anexadas aos lexemas: SELECT 'o:1 carro:2 verde:3 correu:4 mais:5 do:6 que:7 o:8  carro:9 vermelho:10'::tsvector; 'carro':2,9 'correu':4 'do':6 'mais':5 'o':1,8 'que':7 'verde':3 'vermelho':10 ● Em caso de duplicações as posições são delimitadas por vírgulas.
  • 14. SELECT to_tsvector('pg_catalog.portuguese', 'O carro correu, correu e venceu a corrida facilmente,  ultrapassando o último carro a 15 min do final'); '15':15 'carr':2,13 'corr':3,4,8 'facil':9 'final':18 'min':16 'ultrapass':10 'venc':6 'últim':12 Tipos e Respectivas Funções Função to_tsvector ● Converte um documento para tokens, reduz esses tokens para lexemas e retorna um tsvector que lista os lexemas junto com suas posições no documento. ● Stop words eliminadas!
  • 15. SELECT 'rato gato pato'::tsvector;  'gato' 'pato' 'rato' Tipos e Respectivas Funções Função to_tsvector ● to_tsvector != 'string'::tsvector SELECT to_tsvector('rato gato pato');  'gat':2 'pat':3 'rat':1
  • 16. Tipos e Respectivas Funções Tipo tsquery ● Consulta de busca textual; ● Representa um texto de consulta; ● Armazena lexemas que serão base de busca; ● Combinação de lexemas utilizando operadores booleanos: & (AND), | (OR) e ! (NOT); ● Parênteses podem ser usados para reforçar um grupamento de operadores.
  • 17. Tipos e Respectivas Funções Tipo tsquery Exemplos: SELECT 'gato & rato'::tsquery; 'gato' & 'rato' SELECT 'pato & (gato|rato)'::tsquery; 'pato' & ( 'gato' | 'rato' ) SELECT '! 1'::tsquery; !'1'
  • 18. SELECT to_tsquery('pg_catalog.portuguese','!(correr & vencer)'); !( 'corr' & 'venc' ) Tipos e Respectivas Funções Função to_tsquery ● Cria um valor tsquery de um querytext; ● Normaliza cada token em um lexema usando a configuração especificada ou por omissão; ● Similar à função to_tsvector, em to_tsquery, podemos determinar o idioma e normalizar os termos passados para seus radicais: SELECT to_tsquery('pg_catalog.english','!(running & winning)'); !( 'run' & 'win' )
  • 19. Tipos e Respectivas Funções Função to_tsquery ● Também similarmente à função to_tsvector, podemos omitir o primeiro parâmetro da função, cujo efeito se dará por pegar a configuração de busca textual padrão: SELECT to_tsquery('!(correr & vencer)'); !( 'corr' & 'venc' )
  • 20. Tipos e Respectivas Funções Função plainto_tsquery ● Transforma texto sem formação querytext para tsquery; ● O texto é analisado e normalizado como se fosse um tsvector e então o operador booleano & (AND) é inserido entre as palavras sobreviventes: SELECT plainto_tsquery('english', 'The Fat Rats are sleeping with  the cats');  'fat' & 'rat' & 'sleep' & 'cat'
  • 21. Operadores @@ ou @@@ tsvector casa (combina) com tsquery? (ou vice-versa) Exemplos: SELECT to_tsquery('!(gato & rato)') @@ to_tsvector('O gato correu  atrás do rato'); f SELECT to_tsquery('(gato & rato)') @@ to_tsvector('O gato correu  atrás do rato'); t SELECT to_tsquery('(gato & navio)') @@ to_tsvector('O gato correu  atrás do rato'); f
  • 22. Operadores @@ ou @@@ tsvector casa (combina) com tsquery? (ou vice-versa) Exemplos: SELECT to_tsquery('(gato | navio)') @@ to_tsvector('O gato correu  atrás do rato'); t SELECT to_tsquery('gato | rato') @@ to_tsvector('rata'); t
  • 23. Operadores @@ ou @@@ tsvector casa com tsquery? (ou vice-versa) Operações possíveis: ● tsvector @@ tsquery ● tsquery @@ tsvector ● text @@ tsquery → equivalente a to_tsvector(x) @@ y ● text @@ text → equivalente a to_tsvector(x) @@ plainto_tsquery(y)
  • 24. Operadores !! Negação de uma tsquery Exemplos: SELECT !! to_tsquery('gato | rato') @@ to_tsvector('gatas');  f SELECT !! to_tsquery('gato | rato') @@ to_tsvector('abobrinha');  t
  • 25. Operadores @> tsquery contém outra tsquery? Exemplos: SELECT to_tsquery('gato | rato | cão') @> to_tsquery('cão &  rata');  t SELECT to_tsquery('gato | roda') @> to_tsquery('navio & macaco');  f
  • 26. Operadores <@ tsquery está contida em outra tsquery? Exemplos: SELECT to_tsquery('moto & carro') <@ to_tsquery('moto | carro |  ônibus');  t SELECT to_tsquery('moto | carro | ônibus') <@ to_tsquery('moto &  carro');  f
  • 27. Base de Dados db_fts ● Foi criado exclusivamente para esta apresentação e possui apenas uma tabela, a tb_post, cuja estrutura é: ● A tabela tem como função armazenar textos (artigos), cujos campos são id, titulo, texto e tags. Um índice, pk_post, para o campo id. Coluna Tipo id integer titulo character varying(100) texto text tags character varying(200) Índice: "pk_post" PRIMARY KEY, btree (id)
  • 28. Consultas de Busca Textual ● Exemplo de consulta envolvendo concatenação de campos de texto (VARCHAR e TEXT): ● A concatenação dos campos titulo, texto e tags foi convertida para tsvector; ● Só foram exibidos os títulos dos registros, em que a concatenação convertida casasse com a conversão da string “fruta” para texto de consulta de busca textual. SELECT titulo FROM tb_post WHERE  to_tsvector(titulo||' '||texto||' '||tags) @@ to_tsquery('fruta');      Ananás  Limão  Laranjeira
  • 29. Consultas de Busca Textual ● E se eu quiser pesquisar uma frase? ● Ops... A string “presença humana” não é uma tsquery, tokens soltos, sem os operadores “|” (OR) ou “&” (AND) não são permitidos. SELECT titulo FROM tb_post WHERE to_tsvector(titulo||' '||texto||'  '||tags) @@ to_tsquery('presença humana');  ERROR:  syntax error in tsquery: "presença humana"
  • 30. Consultas de Busca Textual ● Então, como fazer?: ● Explicitando o texto tsquery: ● Que tenha as palavras (normalizadas) “presença” e “humana”. SELECT titulo FROM tb_post WHERE to_tsvector(titulo||' '||texto||'  '||tags) @@ to_tsquery('presença & humana');  Música  Lobo
  • 31. Consultas de Busca Textual ● … ou deixar que implicitamente a função plainto_tsquery converta o texto plano passado para o formato tsquery: ● Vale lembrar que a função plainto_tsquery faz a conversão utilizando a lógica AND (E). SELECT titulo FROM tb_post WHERE to_tsvector(titulo||' '||texto||'  '||tags) @@ plainto_tsquery('presença humana');    Música  Lobo
  • 32. Consultas de Busca Textual ● to_tsquery: Requer previamente strings no formato tsquery e então normaliza os tokens para lexemas; ● plainto_tsquery: Converte para o formato tsquery e normaliza para lexemas; ● Sem stop words! SELECT to_tsquery('presença & humana');  'presenc' & 'human' SELECT plainto_tsquery('presença humana');      'presenc' & 'human'
  • 33. Tabela com campo tsvector ● Até aqui os exemplos foram feitos utilizando a conversão em tempo real de campos de texto concatenados para tsvector; ● Serve muito bem para exemplificar, porém, é mais custoso para o servidor de banco de dados; ● Consequentemente mais demorada será a query: EXPLAIN ANALYZE SELECT titulo FROM tb_post WHERE  to_tsvector(titulo||' '||texto||' '||tags) @@  plainto_tsquery('presença humana'); . . .    Total runtime: 12.031 ms
  • 34. Tabela com campo tsvector ● Adição de um campo tsvector na tabela: ● Preenchendo o novo campo com a normalização da concatenação dos campos titulo, texto e tags: ALTER TABLE tb_post ADD COLUMN texto_vetor TSVECTOR; UPDATE tb_post SET texto_vetor = to_tsvector(titulo||' '||texto||' '||tags);
  • 35. Tabela com campo tsvector ● Nova análise dos resultados, agora, com um campo tsvector: ● Uma melhora de desempenho muito evidente, mas tem como ficar ainda melhor... EXPLAIN ANALYZE  SELECT titulo FROM tb_post  WHERE texto_vetor @@ plainto_tsquery('presença humana'); . . .    Total runtime: 0.559 ms
  • 36. Índices GiST e GIN ● Há dois tipos de índices que podem ser usados para acelerar buscas textuais: GiST e GIN; ● Não é obrigatório, mas seu uso beneficia o desempenho de buscas textuais; ● Esses tipos de índices são aplicados a colunas dos tipos tsvector ou tsquery; ● Há diferenças significantes entre os dois tipos de índices, então é importante entender suas características.
  • 37. Índices GiST e GIN Sintaxe: CREATE  INDEX  nome_indice  ON  nome_tabela  USING  gist(nome_coluna); Cria um índice GiST (Generalized Search Tree - Árvore de Busca Generalizada) CREATE  INDEX  nome_indice  ON  nome_tabela  USING  gin(nome_coluna); Cria um índice GIN (Generalized Inverted Index - Índice Invertido Generalizado).
  • 38. Índices GiST ● Um índice GiST tem perdas, o que significa que o índice pode produzir falsos positivos e é necessário checar a linha atual da tabela para eliminar tais falsos positivos (O PostgreSQL faz isso automaticamente quando é preciso). ● Índices GiST têm perdas porque cada documento é representado no índice por uma assinatura de largura fixa. ● Perdas fazem com que haja uma degradação de performance devido a buscas desnecessárias nos registros de uma tabela que se tornam falsos positivos.
  • 39. Índices GiST ● Como o acesso aleatório a registros da tabela é lento, isso limita a utilidade de índices GiST. ● A probabilidade de falsos positivos depende de vários fatores, em particular o número de palavras únicas, então o uso de dicionários para reduzir esse número é recomendado.
  • 40. Índices GIN ● Um índice GIN não tem perdas para consultas padrão, mas sua performance depende logaritmicamente do número de palavras únicas. ● No entanto, índices GIN armazenam apenas as palavras (lexemas) de valores tsvector, e não o peso de suas labels. ● Assim uma rechecagem de uma linha de uma tabela é necessária quando usa uma consulta que envolve pesos.
  • 41. GiST vs GIN: Qual Escolher? Diferenças de performance: ● Buscas GIN são cerca de 3 (três) vezes mais rápidas do que GiST; ● Índices GIN levam um tempo 3 (três) vezes maior para serem construídos do que GiST; ● Índices GIN são moderadamente mais lentos para atualizar do que os índices GiST, mas cerca de 10 (dez) vezes mais lento se o suporte a fast-update for desabilitado; ● GIN são de 2 (duas) a 3 (três) vezes maiores do que índices GiST;
  • 42. GiST vs GIN: Qual Escolher? Resumindo: ● Índices GIN são melhores para dados estáticos porque as buscas são mais rápidas; ● Para dados dinâmicos, os índices GiST são mais rápidos para serem atualizados. Especificamente, índices GiST são muito bons para dados dinâmicos e rápidos se palavras únicas (lexemas) forem abaixo de 100.000 (cem mil), enquanto os índices GIN lidarão melhor quando for acima disso, porém mais lentos para se atualizarem;
  • 43. GiST vs GIN: Qual Escolher? ● Vale lembrar que o tempo de construção de um índice GIN pode frequentemente ser melhorado aumentando o parâmetro maintenance_work_mem, porém isso não tem efeito para um índice GiST; ● Particionamento de grandes coleções e o uso próprio de índices GiST e GIN permite a implementação de buscas muito mais rápidas com atualização online; ● Particionamento pode ser feito no nível da base de dados usando herança de tabelas, ou pela distribuição de documentos sobre servidores e coletando resultados de buscas usando o módulo dblink. Sendo que esse último é possível por uso de funções de ranking em informações locais apenas.
  • 44. Criando um Índice no Campo tsvector (tipo) ● Criação do índice: ● Nova análise no campo de tipo tsvector com índice: CREATE INDEX idx_texto_vetor ON tb_post USING GIN (texto_vetor); EXPLAIN ANALYZE  SELECT titulo FROM tb_post  WHERE texto_vetor @@ plainto_tsquery('presença humana');   . . .  Total runtime: 0.141 ms
  • 46. Campo tsvector Atualizado Automaticamente ● Criação do gatilho: ● Ao inserir ou alterar registros, o trigger tg_texto_vetor aciona a função built-in tsvector_update_trigger, no entanto essa função é limitada... muito limitada! ● Não permite atribuir pesos através da função setweight. CREATE TRIGGER tg_texto_vetor BEFORE INSERT OR UPDATE ON tb_post FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(texto_vetor,'pg_catalog.portuguese',titulo, texto,tags);
  • 47. Campo tsvector Atualizado Automaticamente ● Uma simples inserção de registro: INSERT INTO tb_post (titulo, texto, tags) VALUES ( 'Cidade de São Paulo', 'A cidade de São Paulo é a capital do Estado de mesmo nome e também  a mais populosa do Brasil.', 'metrópole SP caos trânsito violência');
  • 48. Campo tsvector Atualizado Automaticamente ● Consulta envolvendo busca textual: ● O que combina com “sp” no campo texto_vetor? SELECT titulo FROM tb_post WHERE to_tsquery('sp') @@ texto_vetor;  Cidade de São Paulo
  • 49. Classificação de Resultados de Busca ● Classificar resultados é tentar medir o quanto um documento é relevante para uma consulta em particular, de modo que quando houver muitos "casamentos" (matches), os mais relevantes são exibidos primeiro. ● No PostgreSQL há duas funções pré definidas de classificação, que leva em conta léxicos, proximidade e estrutura da informação, que é, considerar o quão frequentes os termos de uma consulta aparecem em um documento, como estão próximos os termos, o quão importante é a parte do documento que ocorre.
  • 50. Classificação de Resultados de Busca ● Porém, o conceito de relevância é vago e varia especificamente para uma aplicação. Aplicações diferentes podem pedir informações adicionais para classificação, e.g.; data de modificação do documento. ● As funções bult-in de classificação são apenas exemplos. Você pode escrever suas próprias funções e / ou combinar seus resultados com fatores adicionais para adequar às suas necessidades específicas.
  • 51. Classificação de Resultados de Busca As duas funções de classificação disponíveis atualmente são: ● ts_rank([ weights float4[], ] vector tsvector,                         query  tsquery  [,  normalization  integer ]) returns float4 Classifica os vetores baseados na frequência da combinação de seus lexemas.
  • 52. Classificação de Resultados de Busca ● ts_rank_cd([  weights  float4[],  ]  vector  tsvector, query tsquery [, normalization integer  ]) returns float4 Computa a classificação para densidade de correlacionamento* (entre palavras) para um dado vetor de documento ou consulta. Esta função requer informação posicional em sua entrada, portanto não funcionará valores tsvector "stripped"**. *Cover Density Ranking. **Submetidos à função strip()
  • 53. Classificação de Resultados de Busca ● Para ambas funções, os argumentos de pesos (weights) oferecem a habilidade de fazer com que as buscas sejam feitas com pesos especificados. ● A ordem crescente dos pesos é D, C, B, A. ● Existe uma função que define o peso de entrada de lexemas: a função setweight; ● Não é possível combinar tsvector_update_trigger com setweight.
  • 54. Classificação de Resultados de Busca ● Uma limitação da função built-in tsvector_update_trigger é tratar todas entradas de coluna de forma parecida. ● Para processar colunas diferentemente, por exemplo, atribuir pesos diferentes para título, tags e o corpo de texto, é necessário escrever uma função customizada. Excluindo o gatilho criado anteriormente: ● Atualizando toda a tabela com novos valores: DROP TRIGGER tg_texto_vetor ON tb_post; UPDATE tb_post SET texto_vetor = setweight(to_tsvector(coalesce(titulo,'')),'A') || setweight(to_tsvector(coalesce(tags,'')),'B') || setweight(to_tsvector(coalesce(texto,'')),'C');
  • 55. Classificação de Resultados de Busca ● Junto aos lexemas, além das posições, há os pesos: ● Criação da função customizada em PL/pgSQL: SELECT texto_vetor FROM tb_post  WHERE texto_vetor @@ to_tsquery('sp');  'brasil':29C 'caos':7B 'capital':17C 'cidad':1A,11C 'estad':19C  'metrópol':5B 'nom':22C 'paul':4A,14C 'popul':27C 'sp':6B  'trânsit':8B 'violênc':9B 'é':15C CREATE OR REPLACE FUNCTION fc_texto_vetor_upd() RETURNS trigger AS  $$ begin   new.fts := setweight(to_tsvector(coalesce(new.titulo,'')),'A') || setweight(to_tsvector(coalesce(new.tags,'')),'B') || setweight(to_tsvector(coalesce(new.texto,'')),'C');   return new; end $$ LANGUAGE plpgsql;
  • 56. Classificação de Resultados de Busca Criação do gatilho: Agora todas atualizações e inserções, fará com que o campo texto_vetor tenha seu(s) valor(es) também com os pesos. CREATE TRIGGER tg_upd_teste BEFORE INSERT OR UPDATE     ON tb_post FOR EACH ROW EXECUTE PROCEDURE fc_texto_vetor_upd();
  • 57. Destacando Resultados na Busca Textual Função ts_headline ● Apresenta o(s) resultado (s) da busca, de modo a exibir a parte de cada documento como está relacionada com a consulta. ● É muito comum, por exemplo, search engines mostrarem fragmentos do documento com os termos de consulta marcados. Sintaxe: ts_headline([ config regconfig, ] document text,  query tsquery [, options text ]) returns text
  • 58. Destacando Resultados na Busca Textual Função ts_headline Exemplo: No exemplo é demonstrado como destacar palavras relativas ao termo pesquisado com HTML. SELECT ts_headline(texto,to_tsquery('fruta'),'StartSel = <strong>,  StopSel =</strong>') FROM tb_post WHERE texto_vetor @@ to_tsquery('laranja'); <strong>fruto</strong> produzido pela laranjeira (Citrus ×  sinensis), uma árvore da família Rutaceae. A laranja é um  <strong>fruto</strong>
  • 60. Dicionários ● Dicionários são usados para eliminar palavras que não devem ser consideradas em uma busca (palavras de parada / stop words) e normalizar palavras em suas formas derivadas para uma base (lexema). ● Apesar de melhorar a qualidade de pesquisa, normalização e remoção de stop words reduzem o tamanho da representação do tsvector de um documento, de forma a melhorar a performance. ● Nem sempre normalização tem um propósito linguístico e geralmente depende da semântica da aplicação.
  • 61. Dicionários Alguns exemplos de normalização: ● Linguística - Dicionários Ispell tentam reduzir palavras de entrada para uma forma normalizada, dicionários stemmer removem o fim de palavras; ● URLs podem ser normalizadas para fazer com que diferentes combinem: http://www.pgsql.ru/db/mw/index.html http://www.pgsql.ru/db/mw/ http://www.pgsql.ru/db/../db/mw/index.html
  • 62. Dicionários Alguns exemplos de normalização: ● Nomes de cores podem ser substituídas por seus valores hexadecimais, por exemplo: red, green, blue, magenta -> FF0000, 00FF00, 0000FF, FF00FF ● Se indexar números, podemos remover alguns dígitos fracionais para reduzir a faixa de possíveis números, por exemplo: 3.14159265359, 3.1415926, 3.14 serão os mesmos após normalização se apenas dois dígitos forem mantidos após o ponto decimal.
  • 63. Dicionários Um dicionário é um programa que aceita um token como entrada e retorna: ➔ Um vetor de lexemas se a entrada é conhecida para o dicionário; ➔ Um vetor vazio se o dicionário conhece o token, mas ele é uma palavra de parada; ➔ NULL se o dicionário não reconhece o token de entrada.
  • 64. Dicionários ● O PostgreSQL fornece dicionários predefinidos para muitas linguagens. Há também templates predefinidos que podem ser usados para criar novos dicionários com parâmetros customizados. ● A regra geral para configurar uma lista de dicionários é alocar primeiramente o mais restrito, mais específico, então os mais gerais depois, fechando com o dicionário mais geral, como um Snowball stemmer ou simples, que reconhecem tudo. ● Cabe ao dicionário específico como tratar stop words.
  • 65. Dicionários ● Por exemplo, os dicionários Ispell primeiro normalizam palavras e depois buscam na lista de palavras de parada, enquanto stemmers Snowball primeiro verificam a lista de palavras de parada. ● A razão para o comportamento diferente é uma tentativa para reduzir o "ruído". ● Para listar os dicionários de uma base de dados, utlizamos o comando do psql: dFd Ou o comando SQL: SELECT * FROM pg_ts_dict;
  • 66. Dicionários Importante! ● A maioria dos tipos de dicionários dependem de arquivos de configuração, como os arquivos de stop words. ● Esses arquivos devem ser armazenados com o encoding UTF-8. ● Normalmente uma sessão lerá um arquivo de configuração de dicionário uma única vez, quando for usado pela primeira vez dentro da sessão. ● Se o arquivo de configuração for modificado e quer forçar as sessões existentes a utilizar seu novo conteúdo, faça: ALTER TEXT SEARCH DICTIONARY dicionário ... Uma solução "dummy" que não mude nenhum valor :)
  • 67. Dicionário Simples ● O template de dicionário simples converte cada token de entrada em caixa baixa (letras minúsculas) e faz a checagem em um arquivo de palavras de parada. ● Se esse token for achado no arquivo, será retornado um vetor vazio, causando o descarte do token. ● Se o token não estiver nessa "lista negra", a forma em letras minúsculas é retornada como um lexema normalizado.
  • 68. Dicionário Simples Teste de lexização: Diretório de buscas textuais: Busca das palavras “foi” e “sim” no arquivo de palavras de parada em português: SELECT ts_lexize('public.dic_simples','SiM');  {sim} $ cd $SHAREDIR/tsearch_data $ egrep 'foi|sim' portuguese.stop  foi
  • 69. Dicionário Simples ● Alternativamente, o dicionário pode ser configurado para reportar o que não for palavra de parada como desconhecida, permitindo serem passadas para o próximo dicionário da lista. Exemplo: SELECT ts_lexize('public.dic_simples','foi');  {} SELECT ts_lexize('public.dic_simples','SiM');  {sim}
  • 70. Dicionário de Sinônimos ● Modelo de dicionário usado para criar dicionários que substituem uma palavra com um sinônimo; ● Frases não são suportadas (usar o modelo thesaurus para isso); ● Um dicionário de sinônimos pode ser usado para superar problemas linguísticos, por exemplo, previnir que um dicionário stemmer reduza a palavra "Paris" para "par"; ● É suficiente ter uma linha Paris paris no dicionário de sinônimo e colocá-lo antes do dicionário portuguese_stem.
  • 71. Dicionário de Sinônimos A função ts_debug exibe o lexema da palavra “Paris”: Criação da linha no arquivo de configuração do dicionário: SELECT * FROM ts_debug('portuguese', 'Paris');    alias   |   description   | token |   dictionaries    |   dictionary    | lexemes  ­­­­­­­­­­­+­­­­­­­­­­­­­­­­­+­­­­­­­+­­­­­­­­­­­­­­­­­­­+­­­­­­­­­­­­­­­­­+­­­­­­­­­  asciiword | Word, all ASCII | Paris | {portuguese_stem} | portuguese_stem | {par} $ echo 'Paris paris' > $SHAREDIR/tsearch_data/sinonimos.syn
  • 72. Dicionário de Sinônimos Criação do dicionário de sinônimos: Adicionando o dicionário criado à configuração de busca textual em português: CREATE TEXT SEARCH DICTIONARY dic_sinonimos (     TEMPLATE = synonym,     SYNONYMS = sinonimos ); ALTER TEXT SEARCH CONFIGURATION portuguese     ALTER MAPPING FOR asciiword     WITH dic_sinonimos, portuguese_stem;
  • 73. Dicionário de Sinônimos Novamente com a função ts_debug, mas agora o teste já conta com o dicionário de sinônimos criado: SELECT * FROM ts_debug('portuguese', 'Paris');    alias   |   description   | token |          dictionaries           |  dictionary   | lexemes  ­­­­­­­­­­­+­­­­­­­­­­­­­­­­­+­­­­­­­+­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­+­­­­­­­­­­­­­­­+­­­­­­­­­  asciiword | Word, all ASCII | Paris | {dic_sinonimos,portuguese_stem} | dic_sinonimos | {paris}
  • 74. Dicionário Thesaurus ● Um dicionário thesaurus (às vezes abreviado como TZ) é uma coleção de palavras que incluem informação sobre a relação entre palavras e frases, por exemplo: termos mais amplos (broader terms: BT), termos mais restritos (narrower terms: NT), termos preferidos, termos não preferidos, termos relacionados, etc. ● Basicamente substitui todos termos não preferidos por um termo preferido e opcionalmente preserva os termos originais para indexação, por exemplo.
  • 75. Dicionário Thesaurus ● Na implementação atual do PostgreSQL do dicionário thesaurus é uma extensão do dicionário de sinônimos com suporte a frase adicionado. ● Esse tipo de dicionário requer um arquivo de configuração no seguinte formato: # comentário palavra(s) de exemplo : palavra(s) indexada(s) mais palavra(s) de exemplo : mais palavra(s) indexada(s) ... O caractere ":" age como um delimitador entre uma frase e sua substituição.
  • 76. Dicionário Thesaurus ● Um dicionário thesaurus usa um subdicionário (que é especificado na configuração de dicionário) para normalizar o texto de entrada antes de checar por frases que combinem. ● É possível selecionar apenas um subdicionário. Um erro é reportado se o subdicionário falha para reconhecer uma palavra. Nesse caso, deve-se remover o uso da palavra ou ensinar o dicionário sobre ela. ● Pode-se colocar um "*" no começo de uma palavra indexada para pular a aplicação do subdicionário para ela, mas todas palavras de exemplo devem ser conhecidas para o subdicionário.
  • 77. Dicionário Thesaurus ● O dicionário thesaurus escolhe a combinação mais longa se há múltiplas frases combinando com a entrada, e os laços são quebrados usando a última definição. ● Stop words específicas reconhecidas pelo subdicionário não podem ser especificadas ao invés de usar "?" para marcar a localização onde qualquer stop word pode aparecer. ** Atenção ** Dicionários do tipo thesaurus são usados durante indexação, então qualquer mudança em seus parâmetros requer reindexação, diferentemente de outros tipos de dicionários.
  • 78. Dicionário Thesaurus Configuração Thesaurus Para definir um novo dicionário thesaurus, use o modelo (template) thesaurus, por exemplo: ● Criação do dicionário thesaurus: $ cp thesaurus_sample.ths pt_br_tz.ths CREATE TEXT SEARCH DICTIONARY dic_pt_br_tz ( /* template */ TEMPLATE = thesaurus,  /* arquivo de configuração (.ths). */ DictFile = pt_br_tz,  /* subdicionário (português Snowball stemmer) */  Dictionary = pg_catalog.portuguese_stem  );
  • 79. Dicionário Thesaurus Agora é possível vincular o dicionário pt_br_tz para os tipos de tokens desejados em uma configuração, por exemplo: ALTER TEXT SEARCH CONFIGURATION portuguese ALTER MAPPING FOR  Asciiword, Asciihword, hword_asciipart WITH  dic_pt_br_tz, portuguese_stem;
  • 81. Dicionário Thesaurus Se for necessário que uma palavra indexada não seja lexemizada, deve ser colocado o asterisco na frente dela: Um teste: Ops! Não deu certo :( O que deu errado? :| $ echo 'sp : *São *Paulo' >> $SHAREDIR/tsearch_data/pt_br_tz.ths SELECT to_tsvector('portuguese','sp');  'sp':1
  • 82. Dicionário Thesaurus ● É preciso fazer com que a(s) alteração(ões) no arquivo de configuração do dicionário seja reconhecida. ● Dentro da sessão simule uma alteração na configuração do dicionário: Efetivamente não houve alteração alguma, mas o arquivo foi relido :) Funcionou!!! :D ALTER TEXT SEARCH DICTIONARY dic_pt_br_tz ( DictFile = pt_br_tz ); SELECT to_tsvector('portuguese','sp');  'Paulo':2 'São':1
  • 83. Dicionário Ispell ● O template (modelo) de dicionário Ispell suporta dicionários morfológicos, que pode normalizar muitas formas linguísticas diferentes de uma palavra em um mesmo lexema. ● Um dicionário Ispell português pode combinar (casar) todas declinações e conjugações de um termo de busca, como verbos irregulares, por exemplo. ● A distribuição padrão do PostgreSQL não inclui qualquer arquivo Ispell de configuração. ● Dicionários para um grande número de idiomas estão disponíveis no Ispell. ● Formatos mais modernos de dicionários também são suportados: MySpell (OO < 2.0.1) e Hunspell (OO >= 2.0.2). Uma vasta lista de dicionários está disponível na Wiki do OpenOffice.
  • 84. Dicionário Ispell Instalação e Configuração Instalação do pacote myspell-pt-br, que proverá os arquivos necessários para o português brasileiro: # aptitude install myspell­pt­br
  • 85. Dicionário Ispell Instalação e Configuração Localizando os arquivos .aff e .dic, que são necessários para gerar os arquivos .affix e .dict, respectivamente: $ ACHADOS=`dpkg ­L myspell­pt­br | egrep '(dic|aff)$'` $ for i in $ACHADOS;  do  if ! [ ­L $i ]; then  echo $i;  fi done /usr/share/hunspell/pt_BR.aff /usr/share/hunspell/pt_BR.dic
  • 86. Dicionário Ispell Gerando os arquivos .dict e .affix, com codificação UTF-8: $ iconv ­f latin1 ­t UTF­8  /usr/share/hunspell/pt_BR.dic > $SHAREDIR/tsearch_data/pt_br.dict $ iconv ­f latin1 ­t UTF­8  /usr/share/hunspell/pt_BR.aff > $SHAREDIR/tsearch_data/pt_br.affix
  • 87. Dicionário Ispell Para criar um dicionário Ispell, use o template built-in e especifique outros parâmetros: CREATE TEXT SEARCH DICTIONARY dic_pt_br_ispell (     TEMPLATE = ispell,     DictFile = pt_br,     AffFile = pt_br,     StopWords = portuguese );
  • 88. Dicionário Ispell ● DictFile, AffFile e StopWords especificam os nomes, respectivamente dos arquivos de dicionário, afixos e palavras de parada. ● Dicionários Ispell normalmente reconhecem um conjunto limitado de palavras, então eles devem ser seguidos por outro dicionário mais amplo, como um dicionário Snowball, que reconhece tudo.
  • 89. Dicionário Ispell ● Dicionários Ispell suportam divisão de palavras compostas, uma característica muito útil. Observação: MySpell não suporte palavras compostas. Hunspell tem suporte sofisticado para palavras compostas. Atualmente, o PostgreSQL implementa apenas operações básicas do Hunspell para palavras compostas.
  • 90. Dicionário Ispell Criação de uma nova configuração de busca textual, usando uma pré existente como modelo: Adicionando o dicionário Ispell criado à configuração: ALTER TEXT SEARCH CONFIGURATION tsc_pt_br     ALTER MAPPING FOR  Asciiword, asciihword,  hword_asciipart, word,  Hword, hword_part         WITH  dic_pt_br_ispell,  portuguese_stem,  simple; CREATE TEXT SEARCH CONFIGURATION tsc_pt_br  ( COPY = pg_catalog.portuguese );
  • 91. Dicionário Ispell Testando (verbos irregulares): SELECT to_tsvector('tsc_pt_br','caberia') @@  to_tsquery('tsc_pt_br','caibo');  t SELECT to_tsvector('tsc_pt_br','eu trouxe!!!');  'trazer':2
  • 92. Dicionário Snowball ● Este template de dicionário é baseado em um projeto de Martin Porter, inventor do popular algoritmo de stemming para o inglês. ● Snowball hoje fornece algoritmo de stemming para muitos idiomas (http://snowball.tartarus.org/). Cada algoritmo entendde como reduzir formas variantes comum de palavras para uma base, ou stem, na ortografia de seu idioma. ● Um dicionário Snowball requer um parâmetro de língua para identificar que stemmer usar, e opcionalmente poder especificar ● um arquivo de palavras de parada que é uma lista de palavras para eliminar. As listas de palavras de parada padrões do PostgreSQL também são fornecidas pelo projeto Snownball.
  • 93. Dicionário Snowball Criação de um dicionário Snowball: ● Um dicionário Snowball reconhece tudo, simplificando uma palavra ou não, então ele deve ser alocado ao final da lista de dicionários. ● É inútil tê-lo antes que qualquer outro dicionário, pois um token nunca passará por ele ao dicionário seguinte. CREATE TEXT SEARCH DICTIONARY portuguese_stem (     TEMPLATE = snowball,     Language = portuguese,     StopWords = portuguese );
  • 94. Configuração de Busca Textual ● Especifica todas opções necessárias para transformar um documento em um tsvector: o parser para quebrar texto em tokens e os dicionários para transformar cada token em um lexema. ● Toda chamada a funções como to_tsvector e to_tsquery necessita de uma configuração para fazer seu processamento. ● O parâmetro de configuração default_text_search_config especifca o nome da configuração padrão, que será é utilizada por funções de buscas textuais se o padrão relativo à configuração de busca textual for omitido.
  • 95. Configuração de Busca Textual ● Essa configuração pode ser configurada no postgresql.conf ou em uma sessão individual utilizando o comando SET. ● Muitas configurações de busca textual pré definidas estão disponíveis, e é possível criar uma customizada facilmente. ● Para facilitar o gerenciamento de objetos de busca textual, um conjunto de comandos SQL está disponível e e há vários comandos do psql que exibem informações sobre objetos de busca textual.
  • 96. Configuração de Busca Textual Como exemplo vamos criar uma configuração chamada tsc_pg, começando pela duplicação da configuração português built-in: Vamos usar uma lista de sinônimos específica do PostgreSQL ($SHAREDIR/tsearch_data/pg_dict.syn), cujo conteúdo será: postgres    pg pgsql       pg postgresql  pg CREATE TEXT SEARCH CONFIGURATION public.tsc_pg (COPY = pg_catalog.portuguese);
  • 97. Configuração de Busca Textual Definiremos o dicionário de sinônimos como este: Agora registraremos o dicionário Ispell portuguese_ispell, que tem seus próprios arquivos de configuração: CREATE TEXT SEARCH DICTIONARY dic_pg (     TEMPLATE = synonym,     SYNONYMS = pg_dict ); CREATE TEXT SEARCH DICTIONARY dic_portuguese_ispell (     TEMPLATE = ispell,     DictFile = pt_br,     AffFile = pt_br,     StopWords = portuguese );
  • 98. Configuração de Busca Textual Configuração dos mapeamentos de palavras na configuração tsc_pg: ALTER TEXT SEARCH CONFIGURATION tsc_pg     ALTER MAPPING FOR asciiword, asciihword, hword_asciipart, word,  hword,  hword_part     WITH dic_pg, dic_portuguese_ispell,  portuguese_stem;
  • 99. Configuração de Busca Textual Testando: SELECT ts_debug ('public.tsc_pg','postgresql'); (asciiword,"Word, all ASCII",postgresql, "{dic_pg,dic_portuguese_ispell,portuguese_stem}",dic_pg,{pg}) SELECT ts_debug ('public.tsc_pg','pgsql');  (asciiword,"Word, all ASCII",pgsql, "{dic_pg,dic_portuguese_ispell,portuguese_stem}",dic_pg,{pg}) SELECT ts_debug ('public.tsc_pg','postgres');  (asciiword,"Word, all ASCII",postgres, "{dic_pg,dic_portuguese_ispell,portuguese_stem}",dic_pg,{pg})
  • 100. Configuração de Busca Textual ● Para listar as configurações existentes podemos fazer das seguintes maneiras: - via psql: dF - via SQL: SELECT cfgname FROM pg_ts_config; ● Configurando a sessão para usar a nova configuração, que foi criada no schema public: Conferindo: SET default_text_search_config = 'public.tsc_pg'; SHOW default_text_search_config;  public.tsc_pg
  • 101. Módulo unaccent ● É um módulo contrib que implementa um dicionário de busca textual que remove acentos de lexemas. ● É um dicionário de filtragem, o que significa que sua saída é sempre passada para o próximo dicionário (se for o caso), ao contrário do comportamento normal de dicionários. Isso permite processamento de busca textual sem considerar acentos. ● A implementação atual do unaccent não pode ser usada como um dicionário de normalização para o dicionário thesaurus.
  • 102. Módulo unaccent Configuração ● RULES é o nome do arquivo que contém a lista de regras de tradução. ● Esse arquivo deve estar armazenado em $SHAREDIR/tsearch_data/, cujo nome deve ter a extensão .rules (tal extensão não deve ser incluída no parâmetro RULES).
  • 103. Módulo unaccent Configuração ● O arquivo de regras deve ter o seguinte formato:       À        A     Á        A     Â        A     Ã        A     Ä        A     Å        A     Æ        A
  • 104. Módulo unaccent ● Cada linha representa um par, consistindo de um caractere com acento seguido que será traduzido pelo seguinte que é sem acento. ● Um exemplo mais completo, que é diretamente útil para a maioria dos idiomas europeus, pode ser encontrado no arquivo unaccent.rules, que é instalado do diretório $SHAREDIR/tsearch_data/ quando o módulo é instalado. ● Para instalar o módulo acesse a base de dados que deseja nela trabalhar com o dicionário unaccent e dê o comando: CREATE EXTENSION unaccent;
  • 105. Módulo unaccent Uso ● Ao instalar a extensão unaccent cria-se um template de busca textual unaccent e um dicionário unaccent baseados nela. ● O dicionário unaccent tem o parâmetro padrão de configuração RULES='unaccent', faz com que seja imediatamente utilizável pelo arquivo unaccent.rules. ● Se preferir, pode alterar o parâmetro, por exemplo: ...ou criar novos dicionários baseados no template. ALTER TEXT SEARCH DICTIONARY unaccent (RULES='minhas_regras');
  • 107. Módulo unaccent Um exemplo de como inserir um dicionário unaccent em uma configuração de busca textual: CREATE TEXT SEARCH CONFIGURATION tsc_pt_unaccent ( COPY = portuguese );
  • 110. Módulo unaccent Função unaccent ● Remove acentos de uma dada string. ● Basicamente, é um invólucro (wrapper) que envolve o dicionário unaccent, mas pode ser usada fora do contexto de busca textual. unaccent([dicionário, ] string) returns text Exemplo: SELECT unaccent('unaccent', 'Hotéis');  Hoteis
  • 112. Muito Obrigado!!! :D Juliano Atanazio juliano777@gmail.com