A GIN (Generalized Inverted Index) is PostgreSQL’s practical choice for searching composite values such as JSONB documents and tsvector text. A common mistake is applying a B-tree expression index to document text: it can support equality or prefix matching, but not arbitrary substrings, and long values can exceed B-tree entry limits. section 4.4
Choose the index according to the predicate:
- Use GIN with to_tsvector for token-oriented full-text queries using @@ and plainto_tsquery. section 4.4
- Use GIN directly on JSONB for containment predicates such as data @> '{"doi": ...}'. section 4.4
- Prefer a focused B-tree expression index for equality on one extracted JSONB field, such as data->>'doi'. section 4.4
Indexing article titles
CREATE INDEX ON test.arxiv USING gin (to_tsvector('english', data->>'title')); SELECT data->'doi' FROM test.arxiv WHERE to_tsvector('english', data->>'title') @@ plainto_tsquery('english', 'modeling of hydrogen'); EXPLAIN ANALYZE reports a Bitmap Index Scan and roughly 5 ms execution, replacing the multisecond sequential scan caused by '%modeling of hydrogen%'. section 4.4
DROP INDEX test.arxiv_lower_idx;
DROP INDEX
CREATE INDEX ON test.arxiv
USING gin (to_tsvector('english', data->>'title'));
CREATE INDEX
Inspect the executable GIN definition for a JSONB-derived title search. section 4.4

