"""Add search_tsv and embedding columns to comm_messages for full-text search indexing. Revision ID: 0035 Revises: 0034_automation_config Create Date: 2026-07-25 """ from __future__ import annotations from typing import Sequence, Union from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import TSVECTOR revision: str = "0035_comm_search_index" down_revision: Union[str, None] = "0034_automation_config" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # Add search_tsv column for full-text search op.add_column( "comm_messages", sa.Column("search_tsv", TSVECTOR, nullable=True), ) # Add embedding column for vector search (768 dimensions matching pgvector) op.execute( "ALTER TABLE comm_messages ADD COLUMN embedding vector(768)" ) # Create GIN index on search_tsv for fast FTS queries op.create_index( "ix_comm_messages_search_tsv", "comm_messages", ["search_tsv"], postgresql_using="gin", ) # Create IVFFlat index on embedding for fast vector search op.execute( "CREATE INDEX IF NOT EXISTS ix_comm_messages_embedding " "ON comm_messages USING ivfflat (embedding vector_cosine_ops) " "WITH (lists = 100)" ) def downgrade() -> None: op.drop_index("ix_comm_messages_embedding", table_name="comm_messages") op.drop_index("ix_comm_messages_search_tsv", table_name="comm_messages") op.drop_column("comm_messages", "embedding") op.drop_column("comm_messages", "search_tsv")