Files
silo-server/migrations/sql/20260713233000_episode_search_indexes.sql
Suspense 808883cf8f feat(search): add scalable TV episode search
Add mixed PostgreSQL and Meilisearch episode search with access-safe hydration, incremental indexing, and regression coverage for explicit all-media searches.\n\nPart of #396
2026-07-14 00:21:46 +02:00

54 lines
1.6 KiB
SQL

-- +goose NO TRANSACTION
-- +goose Up
-- Search evaluates these exact expressions in the episode candidate branch.
-- Build concurrently so large episode catalogs remain readable and writable.
-- Remove INVALID remnants first: IF NOT EXISTS otherwise accepts a failed
-- concurrent build and Goose would record a search index that cannot be used.
-- +goose StatementBegin
DO $$
DECLARE
index_name text;
BEGIN
FOREACH index_name IN ARRAY ARRAY[
'idx_episodes_search_title',
'idx_episodes_search_overview'
] LOOP
IF EXISTS (
SELECT 1
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN pg_index i ON i.indexrelid = c.oid
WHERE n.nspname = 'public'
AND c.relname = index_name
AND NOT i.indisvalid
) THEN
EXECUTE format('DROP INDEX public.%I', index_name);
END IF;
END LOOP;
END;
$$;
-- +goose StatementEnd
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_episodes_search_title
ON public.episodes USING gin (
setweight(
to_tsvector(
'simple',
public.normalize_search_text(
COALESCE(NULLIF(BTRIM(title), ''), 'Episode ' || episode_number::text)
)
),
'A'
)
);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_episodes_search_overview
ON public.episodes USING gin (
to_tsvector('english', COALESCE(overview, ''))
);
-- +goose Down
DROP INDEX CONCURRENTLY IF EXISTS public.idx_episodes_search_overview;
DROP INDEX CONCURRENTLY IF EXISTS public.idx_episodes_search_title;