If you can manipulate a search query, review the coverage density rating ( ts_rank_cd() instead of ts_rank() ) and its normalization parameter .
SELECT v, ts_rank(to_tsvector('english', v), to_tsquery('english', 'productivity')) rank, ts_rank_cd(to_tsvector('english', v), to_tsquery('english', 'productivity')) rankcd, ts_rank_cd(to_tsvector('english', v), to_tsquery('english', 'productivity'), 4) rankcd4, ts_rank_cd(to_tsvector('english', v), to_tsquery('english', 'productivity'), 6) rankcd6 FROM ( VALUES ('production of organic products'::TEXT), ('labour productivity'), ('labour productivity with more unrelated words'), ('labour productivity with more unrelated words and again production'), ('production of productivity'), ('product production') ) d(v)
SQLFiddle
However, I'm not sure how to configure pg_search_scope with normalization .
Alternatively, you may be interested in trigram search , they offer more accurate (character by character) results.
source share