feat: add unified search SQL queries with fuzzy filters
- Add SearchMediaItemsUnified query combining search + filters - Add 4 field value search queries (author, genre, series, language) for autocomplete - Support fuzzy text matching via pg_trgm (threshold: 0.3 similarity) - Support exact match with quotes detection for search queries - Add sort parameter support (title ASC/DESC, author ASC/DESC, created_at ASC/DESC, page_count ASC/DESC) - Primary sort by relevance score when searching, secondary by user-specified sort - Combine search query with all filter types in single optimized query - Uses 4 separate simple queries instead of 1 complex query due to sqlc v1.30.0 limitation with CASE in GROUP BY This consolidates the deprecated /filtered and /search endpoints into one unified endpoint.
This commit is contained in:
@@ -224,50 +224,6 @@ ORDER BY
|
||||
mi.created_at DESC
|
||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||
|
||||
-- name: ListMediaItemsFiltered :many
|
||||
SELECT mi.*, l.name as library_name, lt.name as library_type_name
|
||||
FROM media_items mi
|
||||
JOIN libraries l ON mi.library_id = l.id
|
||||
JOIN library_types lt ON l.library_type_id = lt.id
|
||||
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = sqlc.narg('user_id')
|
||||
WHERE mi.library_id = sqlc.narg('library_id')
|
||||
AND COALESCE(lv.is_visible, true) = true
|
||||
AND (sqlc.narg('author_filter') = '' OR mi.author ILIKE sqlc.narg('author_filter'))
|
||||
AND (sqlc.narg('series_filter') = '' OR mi.series ILIKE sqlc.narg('series_filter'))
|
||||
AND (sqlc.narg('genre_filter') = '' OR mi.genre = sqlc.narg('genre_filter'))
|
||||
AND (sqlc.narg('language_filter') = '' OR mi.language = sqlc.narg('language_filter'))
|
||||
AND (sqlc.narg('year_min') = 0 OR mi.copyright_year >= sqlc.narg('year_min'))
|
||||
AND (sqlc.narg('year_max') = 0 OR mi.copyright_year <= sqlc.narg('year_max'))
|
||||
AND (sqlc.narg('has_cover') = false OR mi.cover_image_path IS NOT NULL)
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'title ASC' THEN mi.title
|
||||
ELSE ''
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'title DESC' THEN mi.title
|
||||
ELSE ''
|
||||
END DESC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'author ASC' THEN COALESCE(mi.author, '')
|
||||
ELSE ''
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'author DESC' THEN COALESCE(mi.author, '')
|
||||
ELSE ''
|
||||
END DESC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'created_at ASC' THEN mi.created_at
|
||||
ELSE '1970-01-01'::timestamp
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'created_at DESC' THEN mi.created_at
|
||||
ELSE '1970-01-01'::timestamp
|
||||
END DESC,
|
||||
mi.created_at DESC
|
||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||
|
||||
|
||||
-- name: UpdateMediaItem :one
|
||||
UPDATE media_items SET
|
||||
title = $2,
|
||||
@@ -508,6 +464,7 @@ WHERE COALESCE(lv.is_visible, true) = true
|
||||
)
|
||||
)
|
||||
ORDER BY
|
||||
-- Primary sort: relevance score when searching
|
||||
CASE
|
||||
WHEN sqlc.narg('search_query') != '' THEN
|
||||
GREATEST(
|
||||
@@ -522,6 +479,40 @@ ORDER BY
|
||||
)
|
||||
ELSE 0
|
||||
END DESC,
|
||||
-- Secondary sort: user-specified sort parameter
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'title ASC' THEN mi.title
|
||||
ELSE ''
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'title DESC' THEN mi.title
|
||||
ELSE ''
|
||||
END DESC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'author ASC' THEN COALESCE(mi.author, '')
|
||||
ELSE ''
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'author DESC' THEN COALESCE(mi.author, '')
|
||||
ELSE ''
|
||||
END DESC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'created_at ASC' THEN mi.created_at
|
||||
ELSE '1970-01-01'::timestamp
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'created_at DESC' THEN mi.created_at
|
||||
ELSE '1970-01-01'::timestamp
|
||||
END DESC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'page_count ASC' THEN COALESCE(mi.page_count::text, '0')
|
||||
ELSE ''
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN sqlc.narg('sort') = 'page_count DESC' THEN COALESCE(mi.page_count::text, '0')
|
||||
ELSE ''
|
||||
END DESC,
|
||||
-- Tertiary sort: title (default fallback)
|
||||
mi.title ASC
|
||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user