diff --git a/package-lock.json b/package-lock.json index adcb1cf6..09232b79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "coryd.dev", - "version": "1.5.16", + "version": "1.5.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "coryd.dev", - "version": "1.5.16", + "version": "1.5.17", "license": "MIT", "dependencies": { "@cdransf/api-text": "^1.5.0", diff --git a/package.json b/package.json index 0124ac7a..11a35ccf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coryd.dev", - "version": "1.5.16", + "version": "1.5.17", "description": "The source for my personal site. Built using 11ty (and other tools).", "type": "module", "engines": { diff --git a/queries/functions/search.psql b/queries/functions/search.psql new file mode 100644 index 00000000..1b4165b7 --- /dev/null +++ b/queries/functions/search.psql @@ -0,0 +1,42 @@ +CREATE OR REPLACE FUNCTION public.search_optimized_index( + search_query text, + page_size integer, + page_offset integer, + types text[] +) RETURNS TABLE( + result_id integer, + url text, + title text, + description text, + tags text, + genre_name text, + genre_url text, + type text, + total_plays integer, + rank real +) AS $$ +BEGIN + RETURN QUERY + SELECT + s.id::integer AS result_id, + s.url, + s.title, + s.description, + array_to_string(s.tags, ', ') AS tags, + s.genre_name, + s.genre_url, + s.type, + s.total_plays, + ts_rank_cd( + to_tsvector('english', s.title || ' ' || s.description || array_to_string(s.tags, ' ')), + plainto_tsquery('english', search_query) + ) AS rank + FROM optimized_search_index s + WHERE + (types IS NULL OR s.type = ANY(types)) + AND plainto_tsquery('english', search_query) @@ + to_tsvector('english', s.title || ' ' || s.description || array_to_string(s.tags, ' ')) + ORDER BY rank DESC + LIMIT page_size OFFSET page_offset; +END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/views/content/links.psql b/queries/views/content/links.psql similarity index 100% rename from views/content/links.psql rename to queries/views/content/links.psql diff --git a/views/content/posts.psql b/queries/views/content/posts.psql similarity index 100% rename from views/content/posts.psql rename to queries/views/content/posts.psql diff --git a/views/feeds/all-content.psql b/queries/views/feeds/all-content.psql similarity index 100% rename from views/feeds/all-content.psql rename to queries/views/feeds/all-content.psql diff --git a/views/feeds/search.psql b/queries/views/feeds/search.psql similarity index 100% rename from views/feeds/search.psql rename to queries/views/feeds/search.psql diff --git a/views/feeds/sitemap.psql b/queries/views/feeds/sitemap.psql similarity index 100% rename from views/feeds/sitemap.psql rename to queries/views/feeds/sitemap.psql diff --git a/views/feeds/syndication.psql b/queries/views/feeds/syndication.psql similarity index 100% rename from views/feeds/syndication.psql rename to queries/views/feeds/syndication.psql diff --git a/views/globals/index.psql b/queries/views/globals/index.psql similarity index 100% rename from views/globals/index.psql rename to queries/views/globals/index.psql diff --git a/views/globals/nav.psql b/queries/views/globals/nav.psql similarity index 100% rename from views/globals/nav.psql rename to queries/views/globals/nav.psql diff --git a/views/globals/pages.psql b/queries/views/globals/pages.psql similarity index 100% rename from views/globals/pages.psql rename to queries/views/globals/pages.psql diff --git a/views/media/books.psql b/queries/views/media/books.psql similarity index 100% rename from views/media/books.psql rename to queries/views/media/books.psql diff --git a/views/media/movies.psql b/queries/views/media/movies.psql similarity index 100% rename from views/media/movies.psql rename to queries/views/media/movies.psql diff --git a/views/media/music/album-releases.psql b/queries/views/media/music/album-releases.psql similarity index 100% rename from views/media/music/album-releases.psql rename to queries/views/media/music/album-releases.psql diff --git a/views/media/music/artists.psql b/queries/views/media/music/artists.psql similarity index 100% rename from views/media/music/artists.psql rename to queries/views/media/music/artists.psql diff --git a/views/media/music/concerts.psql b/queries/views/media/music/concerts.psql similarity index 100% rename from views/media/music/concerts.psql rename to queries/views/media/music/concerts.psql diff --git a/views/media/music/genres.psql b/queries/views/media/music/genres.psql similarity index 100% rename from views/media/music/genres.psql rename to queries/views/media/music/genres.psql diff --git a/views/media/music/listens.psql b/queries/views/media/music/listens.psql similarity index 100% rename from views/media/music/listens.psql rename to queries/views/media/music/listens.psql diff --git a/views/media/music/month/albums.psql b/queries/views/media/music/month/albums.psql similarity index 100% rename from views/media/music/month/albums.psql rename to queries/views/media/music/month/albums.psql diff --git a/views/media/music/month/artists.psql b/queries/views/media/music/month/artists.psql similarity index 100% rename from views/media/music/month/artists.psql rename to queries/views/media/music/month/artists.psql diff --git a/views/media/music/month/genres.psql b/queries/views/media/music/month/genres.psql similarity index 100% rename from views/media/music/month/genres.psql rename to queries/views/media/music/month/genres.psql diff --git a/views/media/music/month/tracks.psql b/queries/views/media/music/month/tracks.psql similarity index 100% rename from views/media/music/month/tracks.psql rename to queries/views/media/music/month/tracks.psql diff --git a/views/media/music/now-playing.psql b/queries/views/media/music/now-playing.psql similarity index 100% rename from views/media/music/now-playing.psql rename to queries/views/media/music/now-playing.psql diff --git a/views/media/music/recent-tracks.psql b/queries/views/media/music/recent-tracks.psql similarity index 100% rename from views/media/music/recent-tracks.psql rename to queries/views/media/music/recent-tracks.psql diff --git a/views/media/music/three-month/albums.psql b/queries/views/media/music/three-month/albums.psql similarity index 100% rename from views/media/music/three-month/albums.psql rename to queries/views/media/music/three-month/albums.psql diff --git a/views/media/music/three-month/artists.psql b/queries/views/media/music/three-month/artists.psql similarity index 100% rename from views/media/music/three-month/artists.psql rename to queries/views/media/music/three-month/artists.psql diff --git a/views/media/music/three-month/genres.psql b/queries/views/media/music/three-month/genres.psql similarity index 100% rename from views/media/music/three-month/genres.psql rename to queries/views/media/music/three-month/genres.psql diff --git a/views/media/music/three-month/tracks.psql b/queries/views/media/music/three-month/tracks.psql similarity index 100% rename from views/media/music/three-month/tracks.psql rename to queries/views/media/music/three-month/tracks.psql diff --git a/views/media/music/week/albums.psql b/queries/views/media/music/week/albums.psql similarity index 100% rename from views/media/music/week/albums.psql rename to queries/views/media/music/week/albums.psql diff --git a/views/media/music/week/artists.psql b/queries/views/media/music/week/artists.psql similarity index 100% rename from views/media/music/week/artists.psql rename to queries/views/media/music/week/artists.psql diff --git a/views/media/music/week/genres.psql b/queries/views/media/music/week/genres.psql similarity index 100% rename from views/media/music/week/genres.psql rename to queries/views/media/music/week/genres.psql diff --git a/views/media/music/week/tracks.psql b/queries/views/media/music/week/tracks.psql similarity index 100% rename from views/media/music/week/tracks.psql rename to queries/views/media/music/week/tracks.psql diff --git a/views/media/shows.psql b/queries/views/media/shows.psql similarity index 100% rename from views/media/shows.psql rename to queries/views/media/shows.psql diff --git a/src/assets/scripts/index.js b/src/assets/scripts/index.js index 06dcf7e3..25c7ad4f 100644 --- a/src/assets/scripts/index.js +++ b/src/assets/scripts/index.js @@ -220,15 +220,20 @@ window.addEventListener("load", () => { total = index.total || results.length; - resultsById = results.reduce((acc, item) => { + const formattedResults = results.map((item) => ({ + ...item, + id: item.result_id, + })); + + resultsById = formattedResults.reduce((acc, item) => { acc[item.id] = item; return acc; }, {}); miniSearch.removeAll(); - miniSearch.addAll(results); + miniSearch.addAll(formattedResults); - return results; + return formattedResults; } catch (error) { console.error("Error fetching search data:", error); return []; diff --git a/workers/search/index.js b/workers/search/index.js index 7ab47eab..928a38a3 100644 --- a/workers/search/index.js +++ b/workers/search/index.js @@ -2,74 +2,38 @@ import { createClient } from "@supabase/supabase-js"; export default { async fetch(request, env) { - const allowedOrigin = "https://coryd.dev"; - const origin = request.headers.get("Origin") || ""; - const referer = request.headers.get("Referer") || ""; + const supabaseUrl = env.SUPABASE_URL; + const supabaseKey = env.SUPABASE_KEY; + const supabase = createClient(supabaseUrl, supabaseKey); - if (!origin.startsWith(allowedOrigin) && !referer.startsWith(allowedOrigin)) - return new Response("Forbidden", { status: 403 }); - - const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_KEY); const { searchParams } = new URL(request.url); const query = searchParams.get("q") || ""; - const types = searchParams.get("type")?.split(",") || []; + const rawTypes = searchParams.getAll("type") || []; + const types = rawTypes.length > 0 ? rawTypes[0].split(",") : null; + const page = parseInt(searchParams.get("page") || "1", 10); const pageSize = parseInt(searchParams.get("pageSize") || "10", 10); const offset = (page - 1) * pageSize; try { - let supabaseQuery = supabase - .from("optimized_search_index") - .select( - "id, title, description, url, tags, type, total_plays, genre_name, genre_url", - { count: "exact" } - ) - .range(offset, offset + pageSize - 1); - - if (types.length > 0) supabaseQuery = supabaseQuery.in("type", types); - - if (query) { - const queryLower = `%${query.toLowerCase()}%`; - supabaseQuery = supabaseQuery.or( - `title.ilike.${queryLower},description.ilike.${queryLower}` - ); - } - - const { data, error, count } = await supabaseQuery; + const { data, error } = await supabase.rpc("search_optimized_index", { + search_query: query, + page_size: pageSize, + page_offset: offset, + types: types.length ? types : null, + }); if (error) { - console.error("Query error:", error); - return new Response(JSON.stringify({ error: "Error fetching data" }), { - status: 500, - }); + console.error("Error fetching search data:", error); + return new Response(JSON.stringify({ results: [] }), { status: 500 }); } - if (!data || data.length === 0) { - console.warn("No results found."); - return new Response( - JSON.stringify({ results: [], total: 0, page, pageSize }), - { headers: { "Content-Type": "application/json" } } - ); - } - - return new Response( - JSON.stringify({ - results: data, - total: count || 0, - page, - pageSize, - }), - { - headers: { - "Content-Type": "application/json", - }, - } - ); + return new Response(JSON.stringify({ results: data }), { + headers: { "Content-Type": "application/json" }, + }); } catch (error) { console.error("Unexpected error:", error); - return new Response(JSON.stringify({ error: "Internal Server Error" }), { - status: 500, - }); + return new Response("Internal Server Error", { status: 500 }); } }, };