CREATE OR REPLACE VIEW optimized_search_index AS WITH search_data AS ( SELECT p.title, p.url::TEXT AS url, p.description AS description, p.tags, NULL AS genre_name, NULL AS genre_url, NULL::TEXT AS total_plays, p.date AS content_date, 'article' AS type, 'post' AS section FROM optimized_posts p UNION ALL SELECT CONCAT(l.title, ' via ', l.name) AS title, l.link::TEXT AS url, l.description AS description, l.tags, NULL AS genre_name, NULL AS genre_url, NULL::TEXT AS total_plays, l.date AS content_date, 'link' AS type, 'link' AS section FROM optimized_links l UNION ALL SELECT CASE WHEN b.rating IS NOT NULL THEN CONCAT(b.title, ' (', b.rating, ')') ELSE b.title END AS title, b.url::TEXT AS url, b.description AS description, b.tags, NULL AS genre_name, NULL AS genre_url, NULL::TEXT AS total_plays, b.date_finished AS content_date, 'books' AS type, 'book' AS section FROM optimized_books b WHERE LOWER(b.status) = 'finished' UNION ALL SELECT ar.name AS title, ar.url::TEXT AS url, ar.description AS description, ARRAY[ar.genre_name] AS tags, CONCAT(COALESCE(ar.emoji, ar.genre_emoji, '🎧'), ' ', ar.genre_name) AS genre_name, ar.genre_slug AS genre_url, TO_CHAR(ar.total_plays::NUMERIC, 'FM999,999,999,999') AS total_plays, NULL AS content_date, 'music' AS type, 'artist' AS section FROM optimized_artists ar UNION ALL SELECT g.name AS title, g.url::TEXT AS url, g.description AS description, NULL AS tags, g.name AS genre_name, g.url AS genre_url, g.total_plays AS total_plays, NULL AS content_date, 'music' AS type, 'genre' AS section FROM optimized_genres g UNION ALL SELECT CONCAT(s.title, ' (', s.year, ')') AS title, s.url::TEXT AS url, s.description AS description, s.tags, NULL AS genre_name, NULL AS genre_url, NULL::TEXT AS total_plays, s.last_watched_at AS content_date, 'tv' AS type, 'show' AS section FROM optimized_shows s WHERE s.last_watched_at IS NOT NULL UNION ALL SELECT CASE WHEN m.rating IS NOT NULL THEN CONCAT(m.title, ' (', m.rating, ')') ELSE CONCAT(m.title, ' (', m.year, ')') END AS title, m.url::TEXT AS url, m.description AS description, m.tags, NULL AS genre_name, NULL AS genre_url, NULL::TEXT AS total_plays, m.last_watched AS content_date, 'movies' AS type, 'movie' AS section FROM optimized_movies m WHERE m.last_watched IS NOT NULL ) SELECT ROW_NUMBER() OVER (ORDER BY url) AS id, * FROM search_data;