Advanced Full-Text Search

1. Using Text Search Dictionaries

DictionaryPurpose
simpleLowercase + stopwords
snowballStemming per language
synonymWord replacement
thesaurusPhrase replacement
ispellMorphological dictionary
unaccentStrip diacritics

2. Creating Custom Dictionary

CREATE TEXT SEARCH DICTIONARY my_dict (
   TEMPLATE = snowball,
   Language = english,
   StopWords = english);

3. Using Simple Dictionary

CREATE TEXT SEARCH DICTIONARY simple_lc (TEMPLATE = simple);
SELECT ts_lexize('simple_lc', 'Running');   -- {running}

4. Using Snowball Dictionary

SELECT ts_lexize('english_stem', 'jumping');   -- {jump}

5. Using Synonym Dictionary

-- $SHAREDIR/tsearch_data/my_syn.syn:  postgres postgresql
CREATE TEXT SEARCH DICTIONARY my_syn (TEMPLATE = synonym, SYNONYMS = my_syn);

6. Using Thesaurus Dictionary

CREATE TEXT SEARCH DICTIONARY my_thes (
   TEMPLATE = thesaurus,
   DictFile = my_thes,
   Dictionary = english_stem);

7. Combining Queries

SELECT * FROM articles
 WHERE tsv @@ (to_tsquery('postgres') && !!to_tsquery('mysql'));
OperatorMeaning
&&AND (combine queries)
||OR
!!NOT
<->Followed by (phrase)
SELECT to_tsvector('quick brown fox') @@ phraseto_tsquery('quick brown');
SELECT to_tsvector('foo bar baz') @@ tsquery('foo <2> baz');     -- distance

9. Using Prefix Matching

SELECT * FROM articles WHERE tsv @@ to_tsquery('postgr:*');

10. Using Weights

UPDATE articles SET tsv =
   setweight(to_tsvector(title), 'A') ||
   setweight(to_tsvector(body),  'B');
WeightDefault Multiplier (ts_rank)
A1.0
B0.4
C0.2
D0.1

11. Filtering by Weight

SELECT * FROM articles
 WHERE tsv @@ to_tsquery('postgres:A');     -- only title hits

12. Using Generated Columns for tsvector

ALTER TABLE articles ADD COLUMN tsv tsvector
   GENERATED ALWAYS AS (
      setweight(to_tsvector('english', coalesce(title,'')), 'A') ||
      setweight(to_tsvector('english', coalesce(body ,'')), 'B')
   ) STORED;
CREATE INDEX articles_tsv_idx ON articles USING gin (tsv);
Note: Replaces older trigger-maintained tsvector pattern; PG 12+.