Obtenir une correspondance partielle à partir de la colonne TSVECTOR indexée par GIN

13

Je voudrais obtenir des résultats en interrogeant ceci:

SELECT * FROM (
  SELECT id, subject
  FROM mailboxes
  WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;

Cela fonctionne et renvoie des lignes avec tsvcontenant Available. Mais si j'utilise avai(abandonné lable), il ne trouve rien.

Toutes les requêtes doivent-elles être dans le dictionnaire? Ne pouvons-nous pas simplement interroger ces lettres? J'ai une base de données qui contient le corps de l'e-mail (contenu) et j'aimerais la rendre rapide à mesure qu'elle grandit à chaque seconde. Actuellement j'utilise

... WHERE content ~* 'letters`
xangr
la source

Réponses:

22

Toutes les requêtes doivent-elles être dans le dictionnaire?

Non. Parce que seuls les tiges de mots (selon la configuration de recherche de texte utilisée ) sont dans l'index pour commencer. Mais plus important:

Non . Parce que, en plus de cela, la recherche en texte intégral est également capable de faire correspondre les préfixes :

Cela fonctionnerait:

SELECT id, subject
FROM   mailboxes
WHERE  tsv @@ to_tsquery('simple', 'avail:*')
ORDER  BY id DESC;

Notez 3 choses:

  1. Utilisez to_tsquery(), non plainto_tsquery(), dans ce cas car (en citant le manuel ):

    ... plainto_tsqueryne reconnaîtra pas les tsqueryopérateurs, les étiquettes de poids ou les étiquettes de correspondance de préfixe dans son entrée

  2. Utilisez la 'simple'configuration de recherche de texte pour générer le tsquerypuisque vous voulez évidemment prendre le mot «prévaloir» tel quel et ne pas appliquer le radical.

  3. Ajouter :*pour en faire une recherche de préfixe, c'est-à-dire trouver tous les lexèmes commençant par 'prévaloir'.

Important: Il s'agit d'une recherche de préfixe sur les lexèmes (tiges de mots) dans le document. Une correspondance d'expression régulière sans caractères génériques ( content ~* 'avail') n'est pas exactement la même! Ce dernier n'est pas ancré à gauche (au début des lexèmes) et trouverait également 'FOOavail' etc.

Il n'est pas clair si vous voulez le comportement décrit dans votre requête ou l'équivalent de l'expression régulière ajoutée. Les index de trigrammes ( pg_trgm) comme @Evan déjà suggéré sont le bon outil pour cela. Il existe de nombreuses questions connexes sur dba.SE, essayez une recherche .

Aperçu:

Démo

SELECT *
FROM (
   VALUES
     ('Zend has no framework')
   , ('Zend Framework')
   ) sub(t), to_tsvector(t) AS tsv
WHERE tsv @@ to_tsquery('zend <-> fram:*');
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1

Réponse connexe récente (chapitre Approche différente pour optimiser la recherche ):

Des courriels?

Puisque vous avez mentionné les e-mails, sachez que l'analyseur de recherche de texte identifie les e-mails et ne les divise pas en mots / lexèmes distincts. Considérer:

SELECT ts_debug('english', '[email protected]')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})

Je remplacerais les séparateurs @et .dans vos courriels par un espace ( ' ') pour indexer les mots contenus.

De plus, étant donné que vous traitez avec des noms dans des e-mails, pas avec des mots anglais (ou une autre langue) , j'utiliserais la 'simple'configuration de recherche de texte pour désactiver le stemming et d'autres fonctionnalités linguistiques :

Construisez la ts_vectorcolonne avec:

SELECT to_tsvector('simple', translate('[email protected]', '@.', '  ')) AS tsv;
Erwin Brandstetter
la source
Je supprime ma réponse parce que de toute façon parce que je me trompe clairement pour la première fois et je préfère ne pas m'en souvenir. J'ai deux questions pour vous 1) où est :*documenté, et 2) une mention pour construire ne devrait-elle pas aller de to_tsvector('simple'..)pair avec des instructions selon lesquelles les requêtes futures de ce tsv nécessiteront également la configuration «simple» pour tsquery? Je pense que vous devriez clarifier les ramifications de la désactivation résultant d'un tsvector / tsquery.
Evan Carroll
@EvanCarroll: L'utilisation de la configuration «simple» n'est pas requise . Cela évite simplement la formation de racines (comme «rats» à «rats») qui peut être souhaitable ou non. Non souhaitable pour l'exemple donné. Manuel: J'ai ajouté des liens ci-dessus ...
Erwin Brandstetter
4
@EvanCarroll: A part: Penser que vous vous trompez la première fois, ce serait la deuxième fois. Et ce serait faux, récursivement. ;)
Erwin Brandstetter
2
@ErwinBrandstetter, Wow, votre chemin m'a donné une recherche à pleine vitesse. Avant votre chemin, il fallait 0.380msdu résultat. Après votre chemin, il a fallu 0.079 ms.
xangr
1
@xangr: Non, FTS ne propose que la mise en correspondance des préfixes pour les lexèmes. Pour plus, regardez pg_trgm. FTS est plus rapide (avec un indice plus petit). Vous pouvez même combiner les deux index ...
Erwin Brandstetter