Other answers clarified that trigram indexes are based on alphanumeric characters only. That's why all your examples match 100 %. You may still be able to make use of a trigram GiST or GIN index *and* establish your desired sort order with additional `ORDER BY` expressions. For your demonstrated case: SELECT my_column, similarity('$ Hello', my_column) AS sml FROM my_table WHERE my_column % '$ Hello' ORDER BY sml DESC , my_column <> '$ Hello' -- ! , my_column; The boolean expression `my_column <> '$ Hello'` evaluates to `FALSE`, `TRUE`, or `NULL` - with *this* sort order. So the exact match (considering *all* characters) comes first. And this query can still use a trigram index. A trigram GiST index would (still) even support a **"nearest neighbor"** (KNN) search with `LIMIT`. Related: - [Search in 300 million addresses with pg_trgm][1] - [Optimizing a postgres similarity query (pg_trgm + gin index)][2] You can do more, depends on your exact use case and requirements. Example: ... ORDER BY sml DESC , my_column <> '$ Hello' , my_column !~ '\$ Hello' -- note $ escaped with \$ , levenshtein(my_column , '$ Hello') , my_column; Within the same trigram similarity, this sorts exact matches first, then strings *containing* the exact phrase. And within each subgroup matches the shorter Levenshtein distance first. Alphabetical as final tiebreaker. Related: - https://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql/10696#10696 - https://dba.stackexchange.com/questions/33137/postgresql-8-4-no-levenshtein-fuzzymatching/33138#33138 - [Escape function for regular expression or LIKE patterns][3] Last but not least, you tagged **[full text search][4]**. But your example is based on trigram similarity (provided by the additional module [`pg_trgm`][5]), which is a largely different concept with completely separate infrastructure and operators. You may want actual full text search instead (and phrase search with that?): - https://dba.stackexchange.com/questions/204588/how-to-search-hyphenated-words-in-postgresql-full-text-search/204601#204601 But punctuation characters are considered noise and stripped in FTS all the same. Same "problem". `ts_debug()` shows how your text search configuration classifies identified tokens in a given string (`simple` configuration in the example). SELECT * FROM ts_debug('simple', '? Hello %&/( 123'); It starts with the "default" parser (which is currently the only one), parsing all these as noise to begin with ... [1]: https://stackoverflow.com/a/44838192/939860 [2]: https://stackoverflow.com/q/43867449/939860 [3]: https://stackoverflow.com/a/45741630/939860 [4]: https://www.postgresql.org/docs/current/textsearch.html [5]: https://www.postgresql.org/docs/current/pgtrgm.html