Skip to content

Instantly share code, notes, and snippets.

@johnidm
Created August 26, 2025 15:07
Show Gist options
  • Save johnidm/11c9598282f1ae0cabde4803c60151f3 to your computer and use it in GitHub Desktop.
Save johnidm/11c9598282f1ae0cabde4803c60151f3 to your computer and use it in GitHub Desktop.
Add a weights to the fields in PostgreSQL full-text search

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment