TSQUERY
TSQUERY is the type of a full-text query expression evaluated against an inverted index with the @@ operator. It is the right-hand operand of every full-text predicate: column @@ tsquery.
Producing a TSQUERY
A TSQUERY is rarely written as a literal. You normally build one of three ways:
- A bare string, analyzed by the column's text search dictionary. Multi-token input matches any token (
ORsemantics). - A constructor function such as
ts_phrase,ts_levenshtein,ts_betweenorto_tsquery. See the function reference. - A cast that changes how a string is interpreted:
'text'::tokenize('dictionary')analyzes with a named dictionary ('keyword'for an exact, un-analyzed token), andquery::boost(factor)scales its score contribution.
SELECT id, body FROM notes_idx WHERE body @@ ts_phrase('quick') ORDER BY id; id | body----+----------------- 1 | quick brown fox 3 | quick red foxComposing queries
TSQUERY values compose with a small set of operators, so a complex search is assembled from simple parts. They fall into three groups:
| Group | Operators |
|---|---|
| Boolean | || (OR), && (AND), !! (NOT) |
| Proximity | ## (phrase / gap) |
| Boost | ^ (score weight) |
A string operand is analyzed by the column's dictionary before it is matched; the ::tokenize cast overrides that analysis.
Boolean operators
|| matches either sub-query:
SELECT id, body FROM notes_idxWHERE body @@ (ts_phrase('brown fox') || ts_phrase('lazy dog'))ORDER BY id; id | body----+----------------- 1 | quick brown fox 2 | lazy dog sleeps&& requires both sub-queries:
SELECT id, body FROM notes_idxWHERE body @@ (ts_phrase('quick') && ts_phrase('fox'))ORDER BY id; id | body----+----------------- 1 | quick brown fox 3 | quick red fox!! is unary NOT; combine it with && to exclude matches — here "quick but not brown":
SELECT id, body FROM notes_idxWHERE body @@ (ts_phrase('quick') && !!ts_phrase('brown'))ORDER BY id; id | body----+--------------- 3 | quick red foxProximity
## requires the operands as an adjacent phrase. a ## N ## b allows an exact N-token gap and a ## [min, max] ## b a gap range:
SELECT id, body FROM notes_idx WHERE body @@ ('brown' ## 'fox') ORDER BY id; id | body----+----------------- 1 | quick brown foxBoost
^ scales a sub-query's contribution to the relevance score without changing which rows match — here doubling the weight of the quick clause:
SELECT id, body FROM notes_idxWHERE body @@ (ts_phrase('fox') || ts_phrase('quick') ^ 2.0)ORDER BY id; id | body----+----------------- 1 | quick brown fox 3 | quick red foxControlling analysis
A string operand is normally analyzed by the column's dictionary. The ::tokenize cast overrides that — ::tokenize('keyword') forces an exact, un-analyzed token match:
SELECT id, body FROM notes_idx WHERE body @@ 'fox'::tokenize('keyword') ORDER BY id; id | body----+----------------- 1 | quick brown fox 3 | quick red foxRelationship to VARCHAR
TSQUERY is reinterpret-compatible with VARCHAR, so a string flows into a TSQUERY position automatically (it is then analyzed as described above). A TSQUERY only has meaning inside an @@ predicate against an indexed column; it is not a general-purpose stored type.
See also
- Full-Text Search — building and running queries
- Full-Text Search Functions — every constructor and operator
- Inverted Index · CREATE TEXT SEARCH DICTIONARY