Files
sori.studio/db/migrations/065_public_search_index.sql
2026-07-03 15:43:27 +09:00

82 lines
2.3 KiB
PL/PgSQL

CREATE EXTENSION IF NOT EXISTS pg_trgm;
ALTER TABLE posts
ADD COLUMN IF NOT EXISTS search_text TEXT NOT NULL DEFAULT '';
ALTER TABLE pages
ADD COLUMN IF NOT EXISTS search_text TEXT NOT NULL DEFAULT '';
CREATE OR REPLACE FUNCTION normalize_public_search_text(value TEXT)
RETURNS TEXT
LANGUAGE sql
IMMUTABLE
AS $$
SELECT lower(trim(regexp_replace(
regexp_replace(
regexp_replace(coalesce(value, ''), E'!\\[[^]]*\\]\\([^)]*\\)', ' ', 'g'),
E'/uploads/[^[:space:])"]+',
' ',
'g'
),
E'[[:space:]]+',
' ',
'g'
)))
$$;
CREATE OR REPLACE FUNCTION set_post_search_text()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW.search_text := normalize_public_search_text(concat_ws(E'\n', NEW.title, NEW.excerpt, NEW.content));
RETURN NEW;
END;
$$;
CREATE OR REPLACE FUNCTION set_page_search_text()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW.search_text := normalize_public_search_text(concat_ws(E'\n', NEW.title, NEW.listing_section, NEW.listing_title, NEW.listing_description, NEW.content));
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS posts_search_text_before_write ON posts;
CREATE TRIGGER posts_search_text_before_write
BEFORE INSERT OR UPDATE OF title, excerpt, content
ON posts
FOR EACH ROW
EXECUTE FUNCTION set_post_search_text();
DROP TRIGGER IF EXISTS pages_search_text_before_write ON pages;
CREATE TRIGGER pages_search_text_before_write
BEFORE INSERT OR UPDATE OF title, listing_section, listing_title, listing_description, content
ON pages
FOR EACH ROW
EXECUTE FUNCTION set_page_search_text();
UPDATE posts
SET search_text = normalize_public_search_text(concat_ws(E'\n', title, excerpt, content));
UPDATE pages
SET search_text = normalize_public_search_text(concat_ws(E'\n', title, listing_section, listing_title, listing_description, content));
CREATE INDEX IF NOT EXISTS posts_public_search_text_trgm_idx
ON posts USING gin (search_text gin_trgm_ops)
WHERE status = 'published';
CREATE INDEX IF NOT EXISTS pages_public_search_text_trgm_idx
ON pages USING gin (search_text gin_trgm_ops)
WHERE status = 'published' AND is_listed = true;
CREATE INDEX IF NOT EXISTS tags_name_trgm_idx
ON tags USING gin ((lower(name)) gin_trgm_ops);
CREATE INDEX IF NOT EXISTS tags_slug_trgm_idx
ON tags USING gin ((lower(slug)) gin_trgm_ops);