Les dictionnaires sont utilisés pour éliminer des mots qui ne devraient pas
être considérés dans une recherche (termes courants),
et pour normaliser des mots pour que des formes
dérivées de ce même mot établissent une correspondance. Un mot normalisé avec
succès est appelé un lexème. En dehors du fait d'améliorer
la qualité de la recherche, la normalisation et la suppression des termes
courants réduisent la taille de la représentation d'un document en
tsvector
, et donc améliorent les performances. La
normalisation n'a pas toujours une signification linguistique et dépend
habituellement de la sémantique de l'application.
Quelques exemples de normalisation :
Linguistique -- les dictionnaires ispell tentent de réduire les mots en entrée en une forme normalisée ; les dictionnaires stemmer suppriment la fin des mots
Les URL peuvent être réduites pour établir certaines correspondances :
http://www.pgsql.ru/db/mw/index.html
http://www.pgsql.ru/db/mw/
http://www.pgsql.ru/db/../db/mw/index.html
Les noms de couleur peuvent être remplacés par leur valeur hexadécimale,
par exemple
red, green, blue, magenta -> FF0000, 00FF00, 0000FF, FF00FF
En cas d'indexation de nombre, nous pouvons supprimer certains chiffres à fraction pour réduire les nombres possibles, donc par exemple 3.14159265359, 3.1415926, 3.14 seront identiques après normalisation si seuls deux chiffres sont conservés après le point décimal.
Un dictionnaire est un programme qui accepte un jeton en entrée et renvoie :
un tableau de lexèmes si le jeton en entrée est connu dans le dictionnaire (notez qu'un jeton peut produire plusieurs lexèmes)
un unique lexème avec le drapeau TSL_FILTER
configuré,
pour remplacer le jeton original avec un nouveau jeton à passer aux
dictionnaires suivants (un dictionnaire de ce type est appelé un
dictionnaire filtrant)
un tableau vide si le dictionnaire connaît le jeton, mais que ce dernier est un terme courant
NULL
si le dictionnaire n'a pas reconnu le jeton en
entrée
PostgreSQL fournit des dictionnaires prédéfinis
pour de nombreuses langues. Il existe aussi plusieurs modèles prédéfinis qui
peuvent être utilisés pour créer de nouveaux dictionnaires avec des paramètres
personnalisés. Chaque modèle prédéfini de dictionnaire est décrit ci-dessous.
Si aucun modèle ne convient, il est possible d'en créer de nouveaux ;
voir le répertoire contrib/
de
PostgreSQL pour des exemples.
Une configuration de recherche plein texte lie un analyseur avec un ensemble
de dictionnaires pour traiter les jetons en sortie de l'analyseur. Pour
chaque type de jeton que l'analyseur peut renvoyer, une liste séparée de
dictionnaires est indiquée par la configuration. Quand un jeton de ce type
est trouvé par l'analyseur, chaque dictionnaire de la liste est consulté
jusqu'à ce qu'un dictionnaire le reconnaisse comme un mot connu. S'il est
identifié comme un terme courant ou si aucun dictionnaire ne le reconnaît,
il sera ignoré et non indexé. Normalement, le premier dictionnaire qui
renvoie une sortie non NULL
détermine le résultat et
tout dictionnaire restant n'est pas consulté ; par contre, un
dictionnaire filtrant peut remplacer le mot donné avec un autre mot qui
est ensuite passé aux dictionnaires suivants.
La règle générale pour la configuration de la
liste des dictionnaires est de placer en premier les dictionnaires les plus
précis, les plus spécifiques, puis les dictionnaires généralistes, en
finissant avec un dictionnaire le plus général possible, comme
un stemmer Snowball ou simple
,
qui reconnaît tout. Par exemple, pour une recherche en astronomie
(configuration astro_en
), vous pouvez lier le type de
jeton asciiword
(mot ASCII) vers un dictionnaire des synonymes
des termes de l'astronomie, un dictionnaire anglais généraliste et un stemmer
Snowball anglais :
ALTER TEXT SEARCH CONFIGURATION astro_en ADD MAPPING FOR asciiword WITH astrosyn, english_ispell, english_stem;
Un dictionnaire filtrant peut être placé n'importe où dans la liste. Cependant, le placer à la fin n'a aucun intérêt. Les dictionnaires filtrants sont utiles pour normaliser partiellement les mots, ce qui permet de simplifier la tâche aux dictionnaires suivants. Par exemple, un dictionnaire filtrant peut être utilisé pour supprimer les accents des lettres accentuées. C'est ce que fait le module unaccent.
Les termes courants sont des mots très courants, apparaissant dans
pratiquement chaque document et n'ont donc pas de valeur discriminatoire.
Du coup, ils peuvent être ignorés dans le contexte de la recherche plein
texte. Par exemple, tous les textes anglais contiennent des mots comme
a
et the
, donc il est inutile de les
stocker dans un index. Néanmoins, les termes courants n'affectent pas les
positions dans tsvector
, ce qui affecte le score :
SELECT to_tsvector('english', 'in the list of stop words'); to_tsvector ---------------------------- 'list':3 'stop':5 'word':6
Les positions 1, 2, 4 manquantes sont dues aux termes courants. Les scores calculés pour les documents avec et sans termes courants sont vraiment différents :
SELECT ts_rank_cd (to_tsvector('english', 'in the list of stop words'), to_tsquery('list & stop')); ts_rank_cd ------------ 0.05 SELECT ts_rank_cd (to_tsvector('english', 'list stop words'), to_tsquery('list & stop')); ts_rank_cd ------------ 0.1
C'est au dictionnaire de savoir comment traiter les mots courants. Par
exemple, les dictionnaires Ispell
normalisent tout
d'abord les mots puis cherchent les termes courants alors que les
stemmers Snowball
vérifient d'abord leur liste de termes
courants. La raison de leur comportement différent est qu'ils tentent de
réduire le bruit.
Le modèle du dictionnaire simple
opère en convertissant
le jeton en entrée en minuscules puis en vérifiant s'il fait partie de la
liste des mots courants qu'il a sur fichier. S'il est trouvé dans ce
fichier, un tableau vide est renvoyé. Le jeton sera alors ignoré.
Dans le cas contraire, la forme minuscule du mot est renvoyée en tant que
lexème normalisé. Autrement, le dictionnaire peut être configuré pour
rapporter les termes courants comme étant non reconnus, ce qui permet de
les passer au prochain dictionnaire de la liste.
Voici un exemple d'une définition de dictionnaire utilisant le modèle
simple
:
CREATE TEXT SEARCH DICTIONARY public.simple_dict ( TEMPLATE = pg_catalog.simple, STOPWORDS = english );
Dans ce cas, english
est le nom de base du fichier
contenant les termes courants. Le nom complet du fichier sera donc
$SHAREDIR/tsearch_data/english.stop
, où
$SHAREDIR
est le répertoire des données partagées de
l'installation de PostgreSQL (souvent
/usr/local/share/postgresql
, mais utilisez
pg_config --sharedir
pour vous en assurer). Le format
du fichier est une simple liste de mots, un mot par ligne. Les lignes
vides et les espaces en fin de mot sont ignorées. Les mots en majuscules
sont basculés en minuscules, mais aucun autre traitement n'est réalisé sur
le contenu de ce fichier.
Maintenant, nous pouvons tester notre dictionnaire :
SELECT ts_lexize('public.simple_dict', 'YeS'); ts_lexize ----------- {yes} SELECT ts_lexize('public.simple_dict', 'The'); ts_lexize ----------- {}
Nous pouvons aussi choisir de renvoyer NULL
à la place
du mot en minuscules s'il n'est pas trouvé dans le fichier des termes
courants. Ce comportement est sélectionné en configurant le paramètre
Accept
du dictionnaire à false
.
En continuant l'exemple :
ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false ); SELECT ts_lexize('public.simple_dict', 'YeS'); ts_lexize ----------- SELECT ts_lexize('public.simple_dict', 'The'); ts_lexize ----------- {}
Avec le paramétrage par défaut d'Accept
(à savoir,
true
), il est préférable de placer un dictionnaire
simple
à la fin de la liste des dictionnaires.
Accept
= false
est seulement utile
quand il y a au moins un dictionnaire après celui-ci.
La plupart des types de dictionnaires se basent sur des fichiers de configuration, comme les fichiers de termes courants. Ces fichiers doivent être dans l'encodage UTF-8. Ils seront traduits vers l'encodage actuel de la base de données, s'il est différent, quand ils seront lus.
Habituellement, une session lira un fichier de configuration du dictionnaire
une seule fois, lors de la première utilisation. Si vous modifiez un fichier
de configuration et que vous voulez forcer la prise en compte des
modifications par les sessions en cours, exécutez une commande
ALTER TEXT SEARCH DICTIONARY
sur le dictionnaire. Cela
peut être une mise à jour « à vide », donc sans réellement
modifier des valeurs.
Ce modèle de dictionnaire est utilisé pour créer des dictionnaires qui
remplacent un mot par un synonyme. Les phrases ne sont pas supportées
(utilisez le modèle thésaurus pour cela, Section 12.6.4).
Un dictionnaire des synonymes peut être utilisé pour contourner des problèmes
linguistiques, par exemple pour empêcher un dictionnaire stemmer anglais de
réduire le mot « Paris » en « pari ». Il suffit d'avoir une ligne
Paris paris
dans le dictionnaire des synonymes et de le
placer avant le dictionnaire english_stem
. Par
exemple :
SELECT * FROM ts_debug('english', 'Paris'); alias | description | token | dictionaries | dictionary | lexemes -----------+-----------------+-------+----------------+--------------+--------- asciiword | Word, all ASCII | Paris | {english_stem} | english_stem | {pari} CREATE TEXT SEARCH DICTIONARY my_synonym ( TEMPLATE = synonym, SYNONYMS = my_synonyms ); ALTER TEXT SEARCH CONFIGURATION english ALTER MAPPING FOR asciiword WITH my_synonym, english_stem; SELECT * FROM ts_debug('english', 'Paris'); alias | description | token | dictionaries | dictionary | lexemes -----------+-----------------+-------+---------------------------+------------+--------- asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris}
Le seul paramètre requis par le modèle synonym
est
SYNONYMS
, qui est le nom de base de son fichier de
configuration -- my_synonyms
dans l'exemple ci-dessus.
Le nom complet du fichier sera
$SHAREDIR/tsearch_data/my_synonyms.syn
(où $SHAREDIR
correspond au répertoire des données
partagées de l'installation de PostgreSQL).
Le format du fichier est une ligne par mot à substituer, avec le mot suivi
par son synonyme séparé par une espace blanche. Les lignes vierges et les
espaces après les mots sont ignorées, les lettres majuscules sont mises
en minuscules.
Le modèle synonym
a aussi un paramètre optionnel, appelé
CaseSensitive
, qui vaut par défaut
false
. Quand CaseSensitive
vaut
false
, les mots dans le fichier des synonymes sont mis
en minuscules, comme les jetons en entrée. Quand il vaut vrai, les mots et
les jetons ne sont plus mis en minuscules, mais comparés tels quels..
Un astérisque (*
) peut être placé à la fin d'un synonyme
dans le fichier de configuration. Ceci indique que le synonyme est un
préfixe. L'astérisque est ignoré quand l'entrée est utilisée dans
to_tsvector()
, mais quand il est utilisé dans
to_tsquery()
, le résultat sera un élément de la
requête avec le marqueur de correspondance du préfixe (voir
Section 12.3.2). Par exemple, supposons
que nous ayons ces entrées dans
$SHAREDIR/tsearch_data/synonym_sample.syn
:
postgres pgsql postgresql pgsql postgre pgsql gogle googl indices index*
Alors nous obtiendrons les résultats suivants :
mydb=# CREATE TEXT SEARCH DICTIONARY syn (template=synonym, synonyms='synonym_sample'); mydb=# SELECT ts_lexize('syn', 'indices'); ts_lexize ----------- {index} (1 row) mydb=# CREATE TEXT SEARCH CONFIGURATION tst (copy=simple); mydb=# ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn; mydb=# SELECT to_tsvector('tst', 'indices'); to_tsvector ------------- 'index':1 (1 row) mydb=# SELECT to_tsquery('tst', 'indices'); to_tsquery ------------ 'index':* (1 row) mydb=# SELECT 'indexes are very useful'::tsvector; tsvector --------------------------------- 'are' 'indexes' 'useful' 'very' (1 row) mydb=# SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst', 'indices'); ?column? ---------- t (1 row)
Un dictionnaire thésaurus (parfois abrégé en TZ) est un ensemble de mots qui incluent des informations sur les relations des mots et des phrases, par exemple des termes plus lointains (BT), plus proches (NT), des termes préférés, des termes non aimés, des termes en relation, etc.
De façon simple, un dictionnaire thésaurus remplace tous les termes par des termes préférés et, en option, conserve les termes originaux pour l'indexage. L'implémentation actuelle du dictionnaire thésaurus par PostgreSQL est une extension du dictionnaire des synonymes avec un support additionnel des phrases. Un dictionnaire thésaurus nécessite un fichier de configuration au format suivant :
# ceci est un commentaire mots(s) : mot(s) indexé(s) d'autre(s) mot(s) : d'autre(s) mot(s) indexé(s) ...
où le deux-points (:
) agit comme un délimiteur entre
une phrase et son remplacement.
Un dictionnaire thésaurus utilise un sous-dictionnaire
(qui est spécifié dans la configuration du dictionnaire) pour normaliser le
texte en entrée avant la vérification des correspondances de phrases. Un
seul sous-dictionnaire est sélectionnable. Une erreur est renvoyée si le
sous-dictionnaire échoue dans la reconnaissance d'un mot. Dans ce cas, vous
devez
supprimer l'utilisation du mot ou le faire connaître au sous-dictionnaire.
Vous pouvez placer un astérisque (*
) devant un mot indexé
pour ignorer l'utilisation du sous-dictionnaire, mais tous les mots
doivent être connus du sous-dictionnaire.
Le dictionnaire thésaurus choisit la plus grande correspondance s'il existe plusieurs phrases correspondant à l'entrée.
Les mots spécifiques reconnus par le sous-dictionnaire ne peuvent pas être
précisés ; à la place, utilisez ?
pour marquer tout
emplacement où un terme courant peut apparaître. Par exemple, en supposant
que a
et the
soient des termes courants
d'après le sous-dictionnaire :
? one ? two : swsw
correspond à a one the two
et à the one a
two
. Les deux pourraient être remplacés par
swsw
.
Comme un dictionnaire thésaurus a la possibilité de reconnaître des phrases,
il doit se rappeler son état et interagir avec l'analyseur. Un dictionnaire
thésaurus utilise ces assignations pour vérifier s'il doit gérer le mot
suivant ou arrêter l'accumulation. Le dictionnaire thésaurus doit être
configuré avec attention. Par exemple, si le dictionnaire thésaurus s'occupe
seulement du type de jeton asciiword
, alors une définition
du dictionnaire thésaurus comme one 7
ne fonctionnera pas,
car le type de jeton uint
n'est pas affecté au dictionnaire
thésaurus.
Les thésaurus sont utilisés lors des indexages pour que toute modification dans les paramètres du dictionnaire thésaurus nécessite un réindexage. Pour la plupart des autres types de dictionnaires, de petites modifications comme l'ajout ou la suppression de termes courants ne demandent pas un réindexage.
Pour définir un nouveau dictionnaire thésaurus, utilisez le modèle
thesaurus
. Par exemple :
CREATE TEXT SEARCH DICTIONARY thesaurus_simple ( TEMPLATE = thesaurus, DictFile = mythesaurus, Dictionary = pg_catalog.english_stem );
Dans ce cas :
thesaurus_simple
est le nom du nouveau dictionnaire
mythesaurus
est le nom de base du fichier de
configuration du thésaurus. (Son nom complet est
$SHAREDIR/tsearch_data/mythesaurus.ths
,
où $SHAREDIR
est remplacé par le répertoire des
données partagées de l'installation.)
pg_catalog.english_stem
est le sous-dictionnaire (ici
un stemmer Snowball anglais) à utiliser pour la normalisation du
thésaurus. Notez que le sous-dictionnaire aura sa propre configuration
(par exemple, les termes courants) qui n'est pas affichée ici.
Maintenant, il est possible de lier le dictionnaire du thésaurus
thesaurus_simple
aux types de jetons désirés dans une
configuration, par exemple :
ALTER TEXT SEARCH CONFIGURATION russian ALTER MAPPING FOR asciiword, asciihword, hword_asciipart WITH thesaurus_simple;
Considérez un thésaurus d'astronomie thesaurus_astro
,
contenant quelques combinaisons de mots d'astronomie :
supernovae stars : sn crab nebulae : crab
Ci-dessous, nous créons un dictionnaire et lions certains types de jetons à un thésaurus d'astronomie et à un stemmer anglais :
CREATE TEXT SEARCH DICTIONARY thesaurus_astro ( TEMPLATE = thesaurus, DictFile = thesaurus_astro, Dictionary = english_stem ); ALTER TEXT SEARCH CONFIGURATION russian ALTER MAPPING FOR asciiword, asciihword, hword_asciipart WITH thesaurus_astro, english_stem;
Maintenant, nous pouvons voir comment cela fonctionne.
ts_lexize
n'est pas très utile pour tester un thésaurus,
car elle traite l'entrée en tant que simple jeton. À la place, nous pouvons
utiliser plainto_tsquery
et
to_tsvector
qui cassera les chaînes en entrée en
plusieurs jetons :
SELECT plainto_tsquery('supernova star'); plainto_tsquery ----------------- 'sn' SELECT to_tsvector('supernova star'); to_tsvector ------------- 'sn':1
En principe, il est possible d'utiliser to_tsquery
si
vous placez l'argument entre guillemets :
SELECT to_tsquery('''supernova star'''); to_tsquery ------------ 'sn'
Notez que supernova star
établit une correspondance avec
supernovae stars
dans thesaurus_astro
,
car nous avions indiqué le stemmer english_stem
dans la
définition du thésaurus. Le stemmer a supprimé e
et
s
.
Pour indexer la phrase originale ainsi que son substitut, incluez-le dans la partie droite de la définition :
supernovae stars : sn supernovae stars SELECT plainto_tsquery('supernova star'); plainto_tsquery ----------------------------- 'sn' & 'supernova' & 'star'
Le modèle de dictionnaire Ispell ajoute le
support
des dictionnaires morphologiques qui peuvent
normaliser plusieurs formes linguistiques différentes d'un mot en un même
lexème. Par exemple, un dictionnaire Ispell
anglais peut établir une correspondance avec toutes les déclinaisons et
conjugaisons du terme bank
, c'est-à-dire
banking
, banked
,
banks
,
banks'
et bank's
.
La distribution standard de PostgreSQL n'inclut aucun des fichiers de configuration Ispell. Les dictionnaires sont disponibles pour un grand nombre de langues à partir du site web Ispell. De plus, certains formats de fichiers dictionnaires plus modernes sont supportés -- MySpell (OO < 2.0.1) et Hunspell (OO >= 2.0.2). Une large liste de dictionnaires est disponible sur le Wiki d'OpenOffice .
Pour créer un dictionnaire Ispell, réalisez les étapes suivantes :
télécharger les fichiers de configuration de dictionnaires. Ces
fichiers OpenOffice portent l'extension
.oxt
. Il est nécessaire d'extraire les fichiers
.aff
et .dic
, et de changer
ces extensions en .affix
et
.dict
. Pour certains fichiers de dictionnaire, il
faut aussi convertir les caractères en encodage UTF-8 avec les commandes
suivantes (par exemple, pour le dictionnaire du norvégien) :
iconv -f ISO_8859-1 -t UTF-8 -o nn_no.affix nn_NO.aff iconv -f ISO_8859-1 -t UTF-8 -o nn_no.dict nn_NO.dic
copier les fichiers dans le répertoire $SHAREDIR/tsearch_data
charger les fichiers dans PostgreSQL avec la commande suivante :
CREATE TEXT SEARCH DICTIONARY english_hunspell ( TEMPLATE = ispell, DictFile = en_us, AffFile = en_us, Stopwords = english);
Ici, DictFile
, AffFile
et
StopWords
indiquent les noms de base des fichiers
dictionnaire, affixes et termes courants. Le fichier des termes courants
a le même format qu'indiqué ci-dessus pour le type de dictionnaire
simple
. Le format des autres fichiers n'est pas indiqué
ici, mais est disponible sur les sites web mentionnés ci-dessus.
Les dictionnaires Ispell reconnaissent habituellement un ensemble limité de mots, pour qu'ils puissent être suivis par un dictionnaire encore plus généraliste ; par exemple un dictionnaire Snowball qui reconnaît tout.
Le fichier .affix
de Ispell
suit la structure suivante :
prefixes flag *A: . > RE # Comme dans enter > reenter suffixes flag T: E > ST # Comme dans late > latest [^AEIOU]Y > -Y,IEST # Comme dans dirty > dirtiest [AEIOU]Y > EST # Comme dans gray > grayest [^EY] > EST # Comme dans small > smallest
Et le fichier .dict
suit la structure suivante :
lapse/ADGRS lard/DGRS large/PRTY lark/MRS
Le format du fichier .dict
est :
basic_form/affix_class_name
Dans le fichier .affix
, chaque règle d'affixe est décrite dans
le format suivant :
condition > [-stripping_letters,] adding_affix
Ici, une condition a un format similaire au format des expressions régulières.
Elle peut comporter des groupements [...]
et [^...]
.
Par exemple, [AEIOU]Y
signifie que la dernière lettre du mot
est "y"
et que l'avant-dernière lettre est "a"
,
"e"
, "i"
, "o"
ou "u"
.
[^EY]
signifie que la dernière lettre n'est ni "e"
ni "y"
.
Les dictionnaires Ispell supportent la séparation des mots composés, une fonctionnalité intéressante. Notez que le fichier d'affixes doit indiquer une option spéciale qui marque les mots du dictionnaire qui peuvent participer à une formation composée :
compoundwords controlled z
Voici quelques exemples en norvégien :
SELECT ts_lexize('norwegian_ispell', 'overbuljongterningpakkmesterassistent'); {over,buljong,terning,pakk,mester,assistent} SELECT ts_lexize('norwegian_ispell', 'sjokoladefabrikk'); {sjokoladefabrikk,sjokolade,fabrikk}
Le format MySpell est un sous-ensemble du
format Hunspell. Le fichier
.affix
de Hunspell suit la
structure suivante :
PFX A Y 1 PFX A 0 re . SFX T N 4 SFX T 0 st e SFX T y iest [^aeiou]y SFX T 0 est [aeiou]y SFX T 0 est [^ey]
La première ligne d'une classe d'affixe est l'en-tête. Les champs des règles d'affixes sont listés après l'en-tête.
nom du paramètre (PFX ou SFX)
flag (nom de la classe d'affixe)
éliminer les caractères au début (au préfixe) ou à la fin (au suffixe) du mot
ajouter l'affixe
condition ayant un format similaire à celui des expressions régulières.
Le fichier .dict
ressemble au fichier .dict
de
Ispell :
larder/M lardy/RT large/RSPMYT largehearted
MySpell ne supporte pas les mots composés. Hunspell a un support sophistiqué des mots composés. Actuellement, PostgreSQL implémente seulement les opérations basiques de Hunspell pour les mots composés.
Le modèle de dictionnaire Snowball est basé sur
le projet de Martin Porter, inventeur du populaire algorithme stemming de
Porter pour l'anglais. Snowball propose maintenant des algorithmes stemming
pour un grand nombre de langues (voir le site Snowball pour plus
d'informations). Chaque algorithme sait comment réduire les variantes
standard d'un mot vers une base, ou stem, en rapport avec la langue. Un
dictionnaire Snowball réclame un paramètre langue
pour
identifier le stemmer à utiliser et, en option, un nom de fichier des
termes courants
donnant une liste de mots à éliminer.
(Les listes de termes courants au standard
PostgreSQL
sont aussi fournies par le projet Snowball.) Par exemple, il existe un
équivalent de la définition interne en
CREATE TEXT SEARCH DICTIONARY english_stem ( TEMPLATE = snowball, Language = english, StopWords = english );
Le format du fichier des termes courants est identique à celui déjà expliqué.
Un dictionnaire Snowball reconnaît tout, qu'il soit ou non capable de simplifier le mot, donc il doit être placé en fin de la liste des dictionnaires. Il est inutile de l'avoir avant tout autre dictionnaire, car un jeton ne passera jamais au prochain dictionnaire.