Ottieni una corrispondenza parziale dalla colonna TSVECTOR indicizzata GIN


13

Vorrei ottenere risultati interrogando questo:

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

Funziona e restituisce righe con tsvcontenimento Available. Ma se uso avai(lasciato cadere lable) non riesce a trovare nulla.

Tutte le query devono essere nel dizionario? Non possiamo semplicemente interrogare tali lettere? Ho un database che contiene un corpo di e-mail (contenuto) e vorrei farlo velocemente man mano che cresce ogni secondo. Attualmente sto usando

... WHERE content ~* 'letters`

Risposte:


22

Tutte le query devono essere nel dizionario?

No. Perché all'inizio sono presenti solo gli stemmi di parole (in base alla configurazione della ricerca di testo utilizzata ). Ma soprattutto:

No . Perché, oltre a ciò, la ricerca full-text è anche in grado di abbinare i prefissi :

Questo funzionerebbe:

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

Nota 3 cose:

  1. Utilizzare to_tsquery(), non plainto_tsquery(), in questo caso perché ( citando il manuale ):

    ... plainto_tsquerynon riconoscerà tsqueryoperatori, etichette di peso o etichette di corrispondenza dei prefissi nei suoi input

  2. Utilizzare la 'simple'configurazione della ricerca di testo per generare il tsquerydato che ovviamente si desidera prendere la parola 'disp' così com'è e non applicare stemming

  3. Aggiungi :*per renderlo una ricerca di prefisso, cioè trova tutti i lessemi che iniziano con 'disp'.

Importante: questa è una ricerca di prefissi sui lessemi (gambi di parole) nel documento. Una corrispondenza di espressioni regolari senza caratteri jolly ( content ~* 'avail') non è esattamente la stessa! Quest'ultimo non è ancorato a sinistra (all'inizio dei lessemi) e troverebbe anche "FOOavail" ecc.

Non è chiaro se si desidera delineare il comportamento nella query o l'equivalente dell'espressione regolare aggiunta. Gli indici Trigram ( pg_trgm) come già suggerito da @Evan sono lo strumento giusto per questo. Ci sono molte domande correlate su dba.SE, prova una ricerca .

Panoramica:

dimostrazione

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

Risposta correlata recente (capitolo Approccio diverso per ottimizzare la ricerca ):

Messaggi di posta elettronica?

Poiché hai menzionato le e-mail, tieni presente che il parser di ricerca del testo identifica le e-mail e non le divide in parole / lessemi separati. Ritenere:

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

Sostituirei i separatori @e .nelle e -mail con spazio ( ' ') per indicizzare le parole contenute.

Inoltre, poiché hai a che fare con i nomi nelle e-mail, non con le parole inglesi (o di qualche altra lingua) , utilizzerei la 'simple'configurazione della ricerca di testo per disabilitare le funzionalità di traduzione e altre lingue :

Costruisci la ts_vectorcolonna con:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;

Sto eliminando la mia risposta per questo perché in entrambi i casi perché ho sbagliato per la prima volta in assoluto e preferirei non ricordarmelo. Ho due domande per te 1) dove è :*documentato, e 2) non dovresti menzionare che to_tsvector('simple'..)vanno di pari passo con le istruzioni che le future interrogazioni di quel tsv richiederanno anche la configurazione "semplice" di tsquery? Penso che dovresti chiarire le conseguenze della disabilitazione derivante da un tsvector / tsquery.
Evan Carroll,

@EvanCarroll: non è necessario utilizzare la configurazione 'semplice' . Evita semplicemente la derivazione (come "ratti" in "ratto") che può o meno essere desiderabile. Non desiderabile per l'esempio fornito. Manuale: ho aggiunto i collegamenti sopra ...
Erwin Brandstetter il

4
@EvanCarroll: A parte: pensare che ti sbagli la prima volta in assoluto, sarebbe la seconda volta. E sarebbe sbagliato, ricorsivamente. ;)
Erwin Brandstetter il

2
@ErwinBrandstetter, Wow, la tua strada mi ha appena dato una ricerca a tutta velocità. Prima della tua strada ci sono voluti 0.380msper ottenere risultati. Dopo la tua strada ci sono voluti 0.079 ms.
xangr,

1
@xangr: No, FTS offre solo la corrispondenza dei prefissi per i lessemi. Per altro, guarda a pg_trgm. FTS è più veloce (con un indice più piccolo). Puoi anche combinare entrambi gli indici ...
Erwin Brandstetter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.