synops/migrations/011_fulltext_search.sql
vegard 26c6a3b8d9 Dynamiske sider (oppgave 14.15): kategori, arkiv, søk, om-side
Implementerer fire nye dynamiske sidetyper for publiseringssamlinger:

- Kategori-sider: filtrert på tag-edges, paginert med cache
- Arkiv: kronologisk med månedsgruppering, paginert med cache
- Søk: PG fulltekst med tsvector/ts_rank, paginert med cache
- Om-side: statisk CAS-node (page_role: "about"), immutable cache

Teknisk:
- Ny migrasjon (011): tsvector-kolonne + GIN-indeks + trigger for søk
- Nye Tera-templates: category.html, archive.html, search.html, about.html
- DynamicPageCache for in-memory caching av dynamiske sider
- Ruter for /pub/{slug}/kategori/{tag}, arkiv, sok, om
- Custom domain-varianter for alle nye sidetyper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:39:06 +00:00

34 lines
1.3 KiB
PL/PgSQL

-- Migrasjon 011: Fulltekstsøk for publiserte artikler
--
-- Legger til tsvector-kolonne på nodes-tabellen og GIN-indeks
-- for effektivt fulltekstsøk i publisert innhold.
-- Brukes av dynamiske søkesider i publiseringssystemet.
-- tsvector-kolonne som oppdateres automatisk via trigger
ALTER TABLE nodes ADD COLUMN IF NOT EXISTS search_vector tsvector;
-- GIN-indeks for rask fulltekstsøk
CREATE INDEX IF NOT EXISTS idx_nodes_search_vector ON nodes USING GIN (search_vector);
-- Trigger-funksjon som oppdaterer search_vector ved insert/update
CREATE OR REPLACE FUNCTION update_search_vector() RETURNS trigger AS $$
BEGIN
NEW.search_vector :=
setweight(to_tsvector('norwegian', COALESCE(NEW.title, '')), 'A') ||
setweight(to_tsvector('norwegian', COALESCE(NEW.content, '')), 'B');
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger på nodes-tabellen
DROP TRIGGER IF EXISTS trg_nodes_search_vector ON nodes;
CREATE TRIGGER trg_nodes_search_vector
BEFORE INSERT OR UPDATE OF title, content ON nodes
FOR EACH ROW
EXECUTE FUNCTION update_search_vector();
-- Populer eksisterende noder
UPDATE nodes SET search_vector =
setweight(to_tsvector('norwegian', COALESCE(title, '')), 'A') ||
setweight(to_tsvector('norwegian', COALESCE(content, '')), 'B')
WHERE search_vector IS NULL;