feat: enhance search with date-prioritized year filtering and true exact matching

Improve media item search functionality with two key enhancements:

1. Date-prioritized year filtering:
   - Prioritize date_published over copyright_year for year range queries
   - Fall back to copyright_year when date_published is NULL
   - Extract year from date_published timestamp for comparison

2. True exact search matching:
   - Replace ILIKE pattern matching with exact equality for quoted queries
   - Use search_query directly instead of wildcard pattern for exact matches
   - Remove SearchPattern parameter and related wildcard logic
   - Add COALESCE handling for author/series NULL values in exact matches

These changes make year filtering more accurate with published dates
and provide genuine exact matching when users wrap queries in quotes.

Refs internal/database/queries/queries.sql:475, internal/services/search.go:62
This commit is contained in:
2026-03-26 15:35:31 -04:00
parent 6b518462f9
commit be31cc88f1
4 changed files with 72 additions and 39 deletions
+9 -8
View File
@@ -59,10 +59,11 @@ func (s *SearchService) parseSearchQuery(query string) (bool, string) {
func (s *SearchService) SearchMediaItemsUnified(ctx context.Context, params SearchParams) ([]database.SearchMediaItemsUnifiedRow, error) {
// Parse search query for exact match detection
isExact, searchQuery := s.parseSearchQuery(params.SearchQuery)
searchPattern := ""
if isExact {
searchPattern = "%" + searchQuery + "%"
}
// For now implementing real exact search. If you want to reimplement wildcard patterns uncomment this and line 81 and check queries.sql line 475 and frontend.go line 211
// searchPattern := ""
// if isExact {
// searchPattern = "%" + searchQuery + "%"
// }
// Build database parameters - only set valid true if filter
dbParams := database.SearchMediaItemsUnifiedParams{
@@ -77,10 +78,10 @@ func (s *SearchService) SearchMediaItemsUnified(ctx context.Context, params Sear
HasCover: pgtype.Bool{Bool: params.HasCover, Valid: true},
SearchQuery: pgtype.Text{String: searchQuery, Valid: true},
IsExactSearch: pgtype.Bool{Bool: isExact, Valid: true},
SearchPattern: pgtype.Text{String: searchPattern, Valid: isExact},
Sort: pgtype.Text{String: params.Sort, Valid: true},
Limit: pgtype.Int4{Int32: int32(params.Limit), Valid: true},
Offset: pgtype.Int4{Int32: int32(params.Offset), Valid: true},
// SearchPattern: pgtype.Text{String: searchPattern, Valid: isExact},
Sort: pgtype.Text{String: params.Sort, Valid: true},
Limit: pgtype.Int4{Int32: int32(params.Limit), Valid: true},
Offset: pgtype.Int4{Int32: int32(params.Offset), Valid: true},
}
if params.LibraryID.Valid {