diff --git a/app/backend/prisma/migrations/00000000000002_persian_fts/migration.sql b/app/backend/prisma/migrations/00000000000002_persian_fts/migration.sql new file mode 100644 index 0000000..d8a29f9 --- /dev/null +++ b/app/backend/prisma/migrations/00000000000002_persian_fts/migration.sql @@ -0,0 +1,31 @@ +-- Persian normalization fn (idempotent via OR REPLACE). +CREATE OR REPLACE FUNCTION teknav_norm_fa(t text) +RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ + SELECT regexp_replace( + translate( + coalesce(t, ''), + E'يكأإآٱ‌ـًٌٍَُِّْ،؛؟', + E'یکاااا ,;?' + ), + '\s+', ' ', 'g' + ); +$$; + +-- Trigram support for autocomplete / fuzzy matching. +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +-- Weighted tsvector computed column (A=title, B=subtitle+summary, C=content). +ALTER TABLE "Article" + ADD COLUMN IF NOT EXISTS "search_tsv" tsvector + GENERATED ALWAYS AS ( + setweight(to_tsvector('simple', teknav_norm_fa("title")), 'A') || + setweight(to_tsvector('simple', teknav_norm_fa(coalesce("subtitle", ''))), 'B') || + setweight(to_tsvector('simple', teknav_norm_fa("summary")), 'B') || + setweight(to_tsvector('simple', teknav_norm_fa("content")), 'C') + ) STORED; + +-- GIN index for full-text search. +CREATE INDEX IF NOT EXISTS "Article_search_tsv_idx" ON "Article" USING GIN ("search_tsv"); + +-- Trigram index for title autocomplete. +CREATE INDEX IF NOT EXISTS "Article_title_trgm_idx" ON "Article" USING GIN ("title" gin_trgm_ops);