fix(search): ensure results are deduplicated

This commit is contained in:
Cory Dransfeldt 2025-06-18 11:16:08 -07:00
parent 5684b461fd
commit 4be7a15a18
No known key found for this signature in database
4 changed files with 38 additions and 30 deletions

18
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "coryd.dev",
"version": "10.7.3",
"version": "10.7.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "coryd.dev",
"version": "10.7.3",
"version": "10.7.4",
"license": "MIT",
"dependencies": {
"minisearch": "^7.1.2",
@ -37,7 +37,7 @@
"postcss-import-ext-glob": "^2.1.1",
"prettier": "3.5.3",
"rimraf": "^6.0.1",
"sql-formatter": "15.6.4",
"sql-formatter": "15.6.5",
"terser": "^5.43.0",
"truncate-html": "^1.2.2"
},
@ -1681,9 +1681,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.169",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.169.tgz",
"integrity": "sha512-q7SQx6mkLy0GTJK9K9OiWeaBMV4XQtBSdf6MJUzDB/H/5tFXfIiX38Lci1Kl6SsgiEhz1SQI1ejEOU5asWEhwQ==",
"version": "1.5.170",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz",
"integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==",
"dev": true,
"license": "ISC"
},
@ -5298,9 +5298,9 @@
"license": "BSD-3-Clause"
},
"node_modules/sql-formatter": {
"version": "15.6.4",
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.4.tgz",
"integrity": "sha512-osSvFAtUu/SqT4ywdPTraCHR/VzMjeG+cXFEGwJJtm2SoA/uewU6Sm2HYyqo6W7VTGSWUWx7WT8KkE3HJq51cA==",
"version": "15.6.5",
"resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.5.tgz",
"integrity": "sha512-fr4TyM1udCSrOHOmouotwUi8dxIDhSLpYNmPePGFVzxq8/i8jd828IapE49QXG7Gzkswxo5WwdAGnYX4YpKoTg==",
"dev": true,
"license": "MIT",
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "coryd.dev",
"version": "10.7.3",
"version": "10.7.4",
"description": "The source for my personal site. Built using 11ty (and other tools).",
"type": "module",
"engines": {
@ -66,7 +66,7 @@
"postcss-import-ext-glob": "^2.1.1",
"prettier": "3.5.3",
"rimraf": "^6.0.1",
"sql-formatter": "15.6.4",
"sql-formatter": "15.6.5",
"terser": "^5.43.0",
"truncate-html": "^1.2.2"
}

View file

@ -1,8 +1,8 @@
CREATE OR REPLACE VIEW optimized_search_index AS
WITH
search_data AS (
SELECT
p.title,
SELECT DISTINCT
ON (p.url) p.title,
p.url::TEXT AS url,
p.description AS description,
p.tags,
@ -15,8 +15,8 @@ WITH
FROM
optimized_posts p
UNION ALL
SELECT
CONCAT(l.title, ' via ', l.name) AS title,
SELECT DISTINCT
ON (l.link) CONCAT(l.title, ' via ', l.name) AS title,
l.link::TEXT AS url,
l.description AS description,
l.tags,
@ -29,8 +29,8 @@ WITH
FROM
optimized_links l
UNION ALL
SELECT
CASE
SELECT DISTINCT
ON (b.url) CASE
WHEN b.rating IS NOT NULL THEN CONCAT(b.title, ' (', b.rating, ')')
ELSE b.title
END AS title,
@ -48,11 +48,11 @@ WITH
WHERE
LOWER(b.status) = 'finished'
UNION ALL
SELECT
ar.name AS title,
SELECT DISTINCT
ON (ar.url) ar.name AS title,
ar.url::TEXT AS url,
ar.description AS description,
ARRAY[ar.genre_name] AS tags,
ARRAY_REMOVE(ARRAY[NULLIF(ar.genre_name, '')], NULL) AS tags,
CONCAT(
COALESCE(ar.emoji, ar.genre_emoji, '🎧'),
' ',
@ -66,8 +66,8 @@ WITH
FROM
optimized_artists ar
UNION ALL
SELECT
g.name AS title,
SELECT DISTINCT
ON (g.url) g.name AS title,
g.url::TEXT AS url,
g.description AS description,
NULL AS tags,
@ -80,8 +80,8 @@ WITH
FROM
optimized_genres g
UNION ALL
SELECT
CONCAT(s.title, ' (', s.year, ')') AS title,
SELECT DISTINCT
ON (s.url) CONCAT(s.title, ' (', s.year, ')') AS title,
s.url::TEXT AS url,
s.description AS description,
s.tags,
@ -96,8 +96,8 @@ WITH
WHERE
s.last_watched_at IS NOT NULL
UNION ALL
SELECT
CASE
SELECT DISTINCT
ON (m.url) CASE
WHEN m.rating IS NOT NULL THEN CONCAT(m.title, ' (', m.rating, ')')
ELSE CONCAT(m.title, ' (', m.year, ')')
END AS title,

View file

@ -117,6 +117,7 @@ description: Search through posts and other content on my site.
let total = 0;
let debounceTimeout;
let isLoading = false;
const resultIds = new Set();
const generateResultHTML = ({ title, url, description, type, tags, genre_name, genre_url, total_plays }) => `
<article class="search__results--result">
@ -215,13 +216,14 @@ description: Search through posts and other content on my site.
}
showLoadingMessage();
$loadMoreButton.style.display = "none";
const results = await loadSearchIndex(query, getSelectedSections(), 1);
currentResults = results;
currentPage = 1;
currentResults = results;
resultIds.clear();
results.forEach((r) => resultIds.add(r.id));
updateSearchResults(results);
};
@ -241,9 +243,15 @@ description: Search through posts and other content on my site.
const nextResults = await loadSearchIndex($input.value.trim(), getSelectedSections(), currentPage);
currentResults = [...currentResults, ...nextResults];
const filteredResults = nextResults.filter((item) => {
if (resultIds.has(item.id)) return false;
resultIds.add(item.id);
return true;
});
updateSearchResults(nextResults);
currentResults = [...currentResults, ...filteredResults];
updateSearchResults(filteredResults);
});
})();
});