diff --git a/docs/developer/api-reference.md b/docs/developer/api-reference.md index a6359bd..046cd43 100644 --- a/docs/developer/api-reference.md +++ b/docs/developer/api-reference.md @@ -365,27 +365,6 @@ Authorization: Bearer } ``` -### Filter & Sort Media Items - -```http -GET /api/media-items/filter -Authorization: Bearer -Content-Type: application/json - -{ - "library_id": "uuid", - "author_filter": "Rowling", - "series_filter": "Harry Potter", - "genre_filter": "Fantasy", - "year_min": 1997, - "year_max": 2007, - "has_cover": true, - "sort": "title ASC", - "limit": 20, - "offset": 0 -} -``` - ### Update Media Item (Admin Only) ```http diff --git a/docs/developer/api/api-reference.md b/docs/developer/api/api-reference.md index c241737..cfdeb29 100644 --- a/docs/developer/api/api-reference.md +++ b/docs/developer/api/api-reference.md @@ -80,7 +80,6 @@ See [Library Management](libraries/) See [Media Item Operations](media-items/) - GET /api/media-items - List media items -- GET /api/media-items/filtered - Filter and sort media items - GET /api/media-items/:id - Get media item details - POST /api/media-items/bulk-delete - Bulk delete media items - POST /api/media-items/bulk-update - Bulk update media items (tags/contributors with normalization) diff --git a/docs/developer/api/media-items/filter_sort_media_items.md b/docs/developer/api/media-items/filter_sort_media_items.md deleted file mode 100644 index 0aa8433..0000000 --- a/docs/developer/api/media-items/filter_sort_media_items.md +++ /dev/null @@ -1,63 +0,0 @@ -# Filter & Sort Media Items - -Filter and sort media items with advanced criteria. - -**Endpoint**: `POST /api/media-items/filter` -**Auth**: Required -**Content-Type**: `application/json` - -## Request Body - -| Field | Type | Required | Description | -| ------------- | ------- | -------- | ----------------------------------------------------------- | -| library_id | string | Yes | Library UUID | -| author_filter | string | No | Filter by author name | -| series_filter | string | No | Filter by series name | -| genre_filter | string | No | Filter by genre | -| year_min | integer | No | Minimum copyright year | -| year_max | integer | No | Maximum copyright year | -| has_cover | boolean | No | Filter by cover image existence | -| sort | string | No | Sort field and order (e.g., "title ASC", "created_at DESC") | -| limit | integer | No | Number of results (default 20) | -| offset | integer | No | Number to skip | - -### Example Request - -```json -{ - "library_id": "uuid", - "author_filter": "Rowling", - "series_filter": "Harry Potter", - "genre_filter": "Fantasy", - "year_min": 1997, - "year_max": 2007, - "has_cover": true, - "sort": "title ASC", - "limit": 20, - "offset": 0 -} -``` - -## Response (200 OK) - -```json -{ - "media_items": [ - { - "id": "uuid", - "title": "Book Title", - "author": "Author Name", - "match_score": 0.95 - } - ], - "total": 7 -} -``` - -## Error Responses - -| Code | Description | -| ---- | ----------------------------------------- | -| 400 | Invalid filter parameters | -| 401 | Invalid or expired token | -| 403 | User does not have access to this library | diff --git a/docs/developer/api/media-items/search_media_items.md b/docs/developer/api/media-items/search_media_items.md index 7037541..84b7444 100644 --- a/docs/developer/api/media-items/search_media_items.md +++ b/docs/developer/api/media-items/search_media_items.md @@ -1,26 +1,43 @@ -# Search Media Items +# Search Media Items (Unified) -Search for media items by title, author, series, tags, or contributors. +Search and filter media items with fuzzy matching support. -**Note:** Search is case-insensitive and punctuation-agnostic. The search query is matched against normalized tags_search and contributors_search fields, allowing users to find matches regardless of casing or punctuation. - -Examples: - -- Search "acme corp" finds items with "ACME CORP." or "Acme Corp" -- Search "oreilly" finds items with "O'Reilly Media" or "OReilly Media" -- Search "science fiction" finds items with "Science-Fiction" or "science-fiction" +**Note:** All text filters use fuzzy matching via PostgreSQL pg_trgm (threshold: 0.3 similarity). This handles typos and partial matches automatically. Use quotes for exact match. **Endpoint**: `GET /api/media-items/search` **Auth**: Required ## Query Parameters -| Parameter | Type | Required | Description | -| --------- | ------- | -------- | ------------------------------------------- | -| q | string | Yes | Search query (minimum 2 characters) | -| library_id| string | No | Filter results to specific library (UUID) | -| limit | integer | No | Number of results (default 20) | -| offset | integer | No | Number to skip | +### Search Parameters + +| Parameter | Type | Required | Description | +| ---------- | ------- | -------- | ---------------------------------------------------- | +| q | string | No | Search query (fuzzy by default, exact in quotes) | +| library_id | string | Yes | Filter to specific library (UUID) | +| limit | integer | No | Number of results (default 50, max 200) | +| offset | integer | No | Number to skip for pagination | + +### Filter Parameters (All Fuzzy Except Years/Booleans) + +| Parameter | Type | Description | +| -------------- | ------- | --------------------------------------------------- | +| author_filter | string | Fuzzy match author field | +| series_filter | string | Fuzzy match series field | +| genre_filter | string | Fuzzy match genre field | +| language_filter| string | Fuzzy match language field | +| year_min | integer | Minimum copyright year (exact range) | +| year_max | integer | Maximum copyright year (exact range) | +| has_cover | boolean | Filter by cover image presence (exact boolean) | + +### Autocomplete Parameters (Field-Specific Search) + +| Parameter | Type | Description | +| ---------- | ------ | ---------------------------------------------- | +| authors | string | Search author values for autocomplete dropdown | +| genres | string | Search genre values for autocomplete dropdown | +| series | string | Search series values for autocomplete dropdown | +| languages | string | Search language values for autocomplete | ## Request Headers @@ -28,43 +45,130 @@ Examples: | ------------- | ------ | -------- | ------------ | | Authorization | string | Yes | Bearer token | -### Example Request +## Search Behavior -Search all libraries: +### Fuzzy Search (Default) + +Handles typos and partial matches automatically: + +- `"asimov"` → matches "Asimov, Isaac", "Asimov, Foundation" +- `"scifi"` → matches "Sci-Fi", "Science Fiction" +- `"azimov"` → matches "Asimov, Isaac" (typo tolerance) + +### Exact Search (With Quotes) + +Use double quotes for exact phrase matching: + +- `"\"Foundation and Empire\""` → only "Foundation and Empire" +- `"\"Asimov, Isaac\""` → only "Asimov, Isaac" + +### Filter Behavior + +**Text filters (fuzzy):** +- `author_filter=asimov` → fuzzy matches author field +- `genre_filter=scifi` → fuzzy matches genre field + +**Exact filters:** +- `year_min=2000&year_max=2010` → exact year range +- `has_cover=true` → exact boolean match + +## Example Requests + +### 1. Global Fuzzy Search + +Search all fields for "foundation": ```http -GET /api/media-items/search?q=Harry+Potter&limit=20&offset=0 +GET /api/media-items/search?library_id=123e4567-e89b-12d3-a456-426614174000&q=foundation Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` -Search within a specific library: +### 2. Fuzzy Author Filter + +Find books by "asimov" (matches "Asimov, Isaac"): ```http -GET /api/media-items/search?q=Harry&library_id=123e4567-e89b-12d3-a456-426614174000&limit=20 +GET /api/media-items/search?library_id=123e4567-e89b-12d3-a456-426614174000&author_filter=asimov Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` +### 3. Combined Search + Filters + +Search "foundation" within books by "asimov": + +```http +GET /api/media-items/search?library_id=123e4567-e89b-12d3-a456-426614174000&q=foundation&author_filter=asimov +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +### 4. Exact Match with Quotes + +Exact phrase search: + +```http +GET /api/media-items/search?library_id=123e4567-e89b-12d3-a456-426614174000&q="Foundation%20and%20Empire" +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +### 5. Multiple Fuzzy Filters + +Fiction books from 2000-2010: + +```http +GET /api/media-items/search?library_id=123e4567-e89b-12d3-a456-426614174000&genre_filter=fiction&year_min=2000&year_max=2010 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +### 6. Field-Specific Search (Autocomplete) + +Get author values for dropdown: + +```http +GET /api/media-items/search?library_id=123e4567-e89b-12d3-a456-426614174000&authors=asimov&limit=50 +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +**Response:** +```json +{ + "results": [ + {"value": "Asimov, Isaac", "count": 47, "score": 0.8}, + {"value": "Asimov, Isaac & Robert Silverberg", "count": 2, "score": 0.75} + ], + "total": 2 +} +``` + ## Response (200 OK) +**Media items search:** +```json +[ + { + "id": "uuid", + "title": "Foundation", + "author": "Asimov, Isaac", + "library_id": "...", + "library_name": "E-Books" + } +] +``` + +**Field values search (autocomplete):** ```json { "results": [ - { - "id": "uuid", - "title": "Book Title", - "author": "Author Name", - "library_id": "...", - "library_name": "E-Books", - "match_score": 0.95 - } + {"value": "Asimov, Isaac", "count": 47, "score": 0.8} ], - "total": 15 + "total": 1 } ``` ## Error Responses -| Code | Description | -| ---- | -------------------------------- | -| 400 | Invalid search query (too short) | -| 401 | Invalid or expired token | +| Code | Description | +| ---- | ---------------------------- | +| 400 | Invalid library_id | +| 400 | Missing library_id | +| 401 | Invalid or expired token | +| 404 | No results found |