Ranking and Relevance Tuning with ts_rank
Weight document sections and tune ranking functions to surface the most relevant results first.
Why Ranking Matters
A full-text query with @@ only tells you whether a document matches a query, not how well. To surface the most relevant rows first, you need a ranking function.
PostgreSQL ships two: ts_rank (frequency-based) and ts_rank_cd (cover-density, considers term proximity). Both return a real score you sort by.
- Matching is binary, fast, and index-backed.
- Ranking is a separate, more expensive computation done on the matched rows.
SELECT title,
ts_rank(to_tsvector('english', body), query) AS rank
FROM articles, to_tsquery('english', 'index & performance') query
WHERE to_tsvector('english', body) @@ query
ORDER BY rank DESC
LIMIT 10;How ts_rank Scores
ts_rank bases its score on term frequency: how often the query lexemes appear in the document, and their assigned weights. More occurrences of a query term generally means a higher score.
Critically, the rank is computed against the tsvector, which stores lexeme positions. A document where the term appears 5 times outranks one where it appears once, all else equal.
ts_rankignores how close terms are to each other.ts_rank_cdrewards documents where query terms cluster together.
All lessons in this course
- Designing tsvector Columns and GIN Indexes
- Ranking and Relevance Tuning with ts_rank
- Fuzzy Matching with pg_trgm Similarity
- Combining Filters with Search Predicates