web-dev-qa-db-fra.com

Obtenir une correspondance partielle à partir de la colonne TSVECTOR de l'indice GIN

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 tsv contenant 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. J'utilise actuellement

... WHERE content ~* 'letters`
13
xangr

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

Non. Parce que seules les tiges Word (en fonction de l'utilisation configuration de recherche de texte ) sont dans l'index pour commencer. Mais plus important:

Non . Parce que, en plus de cela Recherche plein texte est également capable de correspondance de préfixe :

Cela fonctionnerait:

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

Remarque 3 choses:

  1. Utilisez to_tsquery(), pas plainto_tsquery(), dans ce cas parce que ( en citant le manuel ):

    ... plainto_tsquery Ne reconnaîtra pas les opérateurs tsquery, les étiquettes de poids ou les étiquettes de correspondance de préfixe dans son entrée

  2. Utilisez la configuration de recherche de texte 'simple' Pour générer le tsquery puisque vous voulez évidemment prendre le Word 'avail' tel quel et ne pas appliquer le stemming.

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

Important: Il s'agit d'une recherche de préfixe sur les lexèmes (souches Word) 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",[email protected],{simple},simple,{[email protected]})

Je remplacerais les séparateurs @ Et . Dans vos courriels par un espace (' ') Pour indexer les mots contenus.

De plus, comme vous traitez avec names dans les e-mails, pas avec l'anglais (ou une autre langue) words, j'utiliserais le 'simple' configuration de la recherche de texte pour désactiver le stemming et d'autres fonctionnalités language:

Créez la colonne ts_vector Avec:

SELECT to_tsvector('simple', translate('[email protected]', '@.', '  ')) AS tsv;
23
Erwin Brandstetter