From 8eabe3b5e863ce30be910e0ab22e09b392a15c7f Mon Sep 17 00:00:00 2001 From: sirius0xdev Date: Tue, 7 Jul 2026 18:32:02 -0400 Subject: [PATCH] Fix SQLAlchemy 2.0 count().filter(); add search_vector trigger for full-text search --- alembic/versions/001_initial.py | 17 +++++++++++++++++ app/main.py | 6 +++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/alembic/versions/001_initial.py b/alembic/versions/001_initial.py index fc97118..e2e7644 100644 --- a/alembic/versions/001_initial.py +++ b/alembic/versions/001_initial.py @@ -65,6 +65,23 @@ def upgrade() -> None: # Convert events to TimescaleDB hypertable op.execute("SELECT create_hypertable('events', 'ingested_at', if_not_exists => TRUE)") + # Keep search_vector populated from title + body on every insert/update. + op.execute(""" + CREATE OR REPLACE FUNCTION events_search_vector_update() RETURNS trigger AS $$ + BEGIN + NEW.search_vector := + setweight(to_tsvector('english', coalesce(NEW.title, '')), 'A') || + setweight(to_tsvector('english', coalesce(NEW.body, '')), 'B'); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + """) + op.execute(""" + CREATE TRIGGER events_search_vector_trigger + BEFORE INSERT OR UPDATE ON events + FOR EACH ROW EXECUTE FUNCTION events_search_vector_update(); + """) + # GIN index for full-text search op.create_index('ix_events_search_vector', 'events', ['search_vector'], postgresql_using='gin') # Spatial index diff --git a/app/main.py b/app/main.py index 58305cc..16072d9 100644 --- a/app/main.py +++ b/app/main.py @@ -506,9 +506,9 @@ async def get_dashboard_summary(): # Sentiment breakdown (last 24h) def sentiment_query(): return select( - func.count().where(events.c.sentiment_label == "positive").label("pos"), - func.count().where(events.c.sentiment_label == "neutral").label("neu"), - func.count().where(events.c.sentiment_label == "negative").label("neg"), + func.count().filter(events.c.sentiment_label == "positive").label("pos"), + func.count().filter(events.c.sentiment_label == "neutral").label("neu"), + func.count().filter(events.c.sentiment_label == "negative").label("neg"), func.avg(events.c.sentiment_score).label("avg"), ).where(events.c.ingested_at >= yesterday)