Install the extension
The database encoding must beUTF8 or SQL_ASCII. CREATE EXTENSION tin refuses other encodings (for example, LATIN1).
Create a table and index
The example below creates a table, inserts rows, and creates a TIN index on thetext column:
Jalapeño and jalapeno match, and ”😀” is searchable. The same tokenizer applies to indexed columns and queries.
You can preview how a string is tokenized with tin.tokenize:
WITH (k1, b, tokenizer, …). After changing analysis options on a populated index, REINDEX so existing rows are re-tokenized.
Your first queries
TINQL keywords are UPPERCASE. Lowercase tokens are terms. Quote a multi-word phrase (“fuji apple”).Filter
Ranked results (BM25)
Order responses in a ranked list withtin.score
tin.max_score(ctid), which is constant for the scan and identical on every row:
tin.score and tin.max_score require a TIN index scan in the same query. Outside that context, they raise an error rather than returning NULL.
Count
count(*) over a TIN predicate is answered from the index, not a heap scan.
Highlight
tin.highlight adds markers around the text that produced the match. A match on apple returns '<b>apple</b>'.
tin.highlight is configurable, pass in additional arguments to customize the markers and perform the search.
Search across columns
Each TIN index covers one text column. Index every column you want to search, then combine==> in SQL. tin.score(ctid) combines BM25 relevance across those fields for the row. To weight one column higher than another, use TINQL boost (^N) on that field’s query.
For example, name ==> 'fuji^1.5' makes a name match count 1.5 times an unboosted notes match.

