The answer from @sharez is really useful (especially if you need both a tsvector column and index). If you only need the tsvector GIN index and not the extra column, then you can use one of the approaches below.
Read the very helpful and concise PostgreSQL documentation section on Full Text Search - Tables and Indexes for a straightforward explanation of full text search without an index, with an index, and with a column plus an index. Pay attention to the following paragraph from those docs when using an index only approach (where it says "above", you can refer to the index creation examples below if you choose not to read the docs even though they are better than my commentary).
Because the two-argument version of to_tsvector was used in the index above, only a query reference that uses the 2-argument version of to_tsvector with the same configuration name will use that index. That is, WHERE to_tsvector('english', body) @@ 'a & b' can use the index, but WHERE to_tsvector(body) @@ 'a & b' cannot. This ensures that an index will be used only with the same configuration used to create the index entries.
The "two-argument version" refers to the configuration argument, such as 'english', and the field(s) argument. Yes, you are required to pass the configuration argument when creating the index (see the docs for more explanation), so you will also need it in your queries.
First example below creates a tsvector GIN index on a single column, second example creates the index on multiple columns. Note that the comma following Index(...) in __table_args__ is not a style choice, the value of __table_args__ must be a tuple, dictionary, or None.
Single column:
from sqlalchemy import Column, Index, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
Base = declarative_base()
class Example(Base):
__tablename__ = 'examples'
id = Column(Integer, primary_key=True)
textsearch = Column(String)
__table_args__ = (
Index(
'ix_examples_tsv',
func.to_tsvector('english', textsearch),
postgresql_using='gin'
),
)
Multiple columns using text():
from sqlalchemy import Column, Index, Integer, String, text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
Base = declarative_base()
def to_tsvector_ix(*columns):
s = " || ' ' || ".join(columns)
return func.to_tsvector('english', text(s))
class Example(Base):
__tablename__ = 'examples'
id = Column(Integer, primary_key=True)
atext = Column(String)
btext = Column(String)
__table_args__ = (
Index(
'ix_examples_tsv',
to_tsvector_ix('atext', 'btext'),
postgresql_using='gin'
),
)