I have to search for hyphenated words like 'good-morning', 'good-evening', etc.
My query is:
select id, ts_headline(content,
to_tsquery('english','good-morning'),
'HighlightAll=true MaxFragments=100 FragmentDelimiter=$')
from table
where ts_content @@ to_tsquery('english','good-morning');
When executing this query I also get results of 'good' and 'morning' separately. But I want exactly matching words and fragments.
(For ts_content
I used the same default config english
to create the tsvector
.)
How can I search such hyphenated words in PostgreSQL full text search?
Best Answer
The key word here is phrase search, introduced with Postgres 9.6.
Use the
tsquery
FOLLOWED BY operator<->
or one of the related<N>
operators. Or better yet, use the functionphraseto_tsquery()
to generate yourtsquery
.Quoting the manual, it ...
And:
Your query would work like this:
phraseto_tsquery('english', 'good-morning')
generates thistsquery
:Since "good-morning" is identified as
asciihword
(hyphenated ASCII word), the stemmed complete word is added before the components. The manual:to_tsvector()
basically does the same on the other end, so everything matches up. This allows for fine-grained options with hyphenated words. The above only finds "good-morning" with a hyphen (or variants stemming to the same). To find all strings with "good" followed by "morn" (or variants stemming to the same) usephraseto_tsquery('english','good morning')
generating this tsquery:'good' <-> 'morn'
OTOH, you can enforce exact matches by adding another filter like:
Or:
Seems a bit redundant to the human eye, but this way you get fast full text index support and exact matches.
The latter is mostly equivalent, but different (fewer) characters have special meaning in the
LIKE
pattern and might need escaping. Related:Example to demonstrate the operator
<N>
:phraseto_tsquery('english', 'Juliet and the Licks')
generates thistsquery
:<3>
meaning thatlick
must be the third lexeme afterjuliet
.