Problem:
The search API was returning duplicate media items when searching across
libraries. For example, searching for "Harry" with 2 books would return
4-8 results instead of 2, depending on how many users had library visibility
entries.
Root Cause:
The SearchMediaItemsUnified query uses a LEFT JOIN with library_visibility:
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = $1
When multiple library_visibility entries exist for the same library
(e.g., one per user during testing), the LEFT JOIN can create duplicate
rows for each media_item. The query didn't have a DISTINCT clause to
eliminate these duplicates.
Solution:
Added DISTINCT ON (mi.id) clause with mi.id as the first ORDER BY expression:
SELECT DISTINCT ON (mi.id) mi.*, ...
FROM media_items mi
...
ORDER BY mi.id, <other_sort_criteria>
This ensures that even if the LEFT JOIN produces multiple rows per
media_item, only one row per mi.id is returned, preserving the first
occurrence based on the relevance sorting.
Impact:
- Search results now correctly return unique media items
- Test TestCollectionSearchLibraryFilter will pass after database cleanup
- No API changes required - this is purely a query optimization
Note: After deploying this change, residual test data should be cleaned up
with: docker-compose down -v && docker-compose up -d
Files changed:
- internal/database/queries/queries.sql: Added DISTINCT ON clause
- internal/database/queries.sql.go: Regenerated from sqlc