You can give different weights to the fields in PostgreSQL full-text search by using setweight()
inside your to_tsvector
.
SELECT
id,
title,
area,
tags,
content,
url,
ts_rank(
setweight(to_tsvector('portuguese', coalesce(title, '')), 'A') ||
setweight(to_tsvector('portuguese', coalesce(area, '')), 'B') ||
setweight(to_tsvector('portuguese', coalesce(content, '')), 'C') ||
setweight(to_tsvector('portuguese', coalesce(tags, '')), 'D'),
query
) AS relevance_score
FROM
contextual_help_articles,
to_tsquery('portuguese', 'Contabilidade | Fiscal | Apoio | Importação | ECD') AS query
WHERE
(
setweight(to_tsvector('portuguese', coalesce(title, '')), 'A') ||
setweight(to_tsvector('portuguese', coalesce(area, '')), 'B') ||
setweight(to_tsvector('portuguese', coalesce(content, '')), 'C') ||
setweight(to_tsvector('portuguese', coalesce(tags, '')), 'D')
) @@ query
ORDER BY
relevance_score DESC
LIMIT 40;
Explanation:
setweight(tsvector, 'A'|'B'|'C'|'D')
assigns different weights.
'A'
is the highest (title, for example).'B'
is lower (area).'C', 'D'
are progressively lower (content, tags).
Then ts_rank
takes the weighted vector and adjusts the ranking accordingly.
👉 In your case, you probably want something like:
- Title →
'A'
- Area →
'B'
- Content →
'C'
- Tags →
'D'
That way, matches in title weigh more than in content.