Full-text search with PostgreSQL and tsvector

Maria Garcia Feb 2026
2 tabs
-- Create table with tsvector column
CREATE TABLE articles (
  id SERIAL PRIMARY KEY,
  title VARCHAR(200),
  content TEXT,
  author VARCHAR(100),
  published_at TIMESTAMP,
  search_vector tsvector
);

-- Populate search vector (combines title and content)
UPDATE articles
SET search_vector =
  setweight(to_tsvector('english', COALESCE(title, '')), 'A') ||
  setweight(to_tsvector('english', COALESCE(content, '')), 'B');

-- Create GIN index for fast searching
CREATE INDEX idx_articles_search ON articles USING GIN(search_vector);

-- Basic search query
SELECT title, content
FROM articles
WHERE search_vector @@ to_tsquery('english', 'postgresql & performance');

-- Search with OR
SELECT title
FROM articles
WHERE search_vector @@ to_tsquery('english', 'database | sql');

-- Search with NOT
SELECT title
FROM articles
WHERE search_vector @@ to_tsquery('english', 'postgresql & !mysql');

-- Phrase search (words in order)
SELECT title
FROM articles
WHERE search_vector @@ phraseto_tsquery('english', 'query optimization');

-- Plain text search (auto-converts to tsquery)
SELECT title
FROM articles
WHERE search_vector @@ plainto_tsquery('english', 'database performance tuning');

-- Web search syntax (PostgreSQL 11+)
SELECT title
FROM articles
WHERE search_vector @@ websearch_to_tsquery('english',
  '"database optimization" -mysql OR postgresql');

-- Ranking results by relevance
SELECT
  title,
  ts_rank(search_vector, query) AS rank
FROM articles,
     to_tsquery('english', 'postgresql & performance') query
WHERE search_vector @@ query
ORDER BY rank DESC;

-- Advanced ranking (weights title higher)
SELECT
  title,
  ts_rank_cd(search_vector, query, 32) AS rank
FROM articles,
     to_tsquery('english', 'database') query
WHERE search_vector @@ query
ORDER BY rank DESC;

-- Highlight matches
SELECT
  title,
  ts_headline('english', content, query,
    'StartSel=<mark>, StopSel=</mark>, MaxWords=50') AS snippet
FROM articles,
     to_tsquery('english', 'postgresql') query
WHERE search_vector @@ query;
2 files · sql Explain with highlit

Full-text search finds documents matching text queries. PostgreSQL tsvector stores processed documents optimized for search. I use tsquery for search queries with operators—AND, OR, NOT. GIN indexes on tsvector columns enable fast search. Text search configurations handle language-specific stemming. Ranking functions score results by relevance. Phrase search finds exact multi-word matches. Highlighting shows matched terms in context. Full-text search outperforms LIKE for text-heavy applications. Understanding lexemes, dictionaries, and configurations improves search quality. Triggers maintain tsvector columns automatically. Full-text search is essential for content management, documentation, e-commerce. PostgreSQL's built-in search rivals dedicated search engines for many use cases.