docs: update Bruno collection with unified search endpoints
- Update Search All Libraries.yml with expanded documentation - Add Fuzzy Author Filter.yml (author_filter=asimov example) - Add Fuzzy Genre Filter.yml (genre_filter=scifi example) - Add Combined Search and Filters.yml (q=foundation&author_filter=asimov example) - Add Exact Match With Quotes.yml (q="Foundation and Empire" example) - Add Field Values Search - Authors.yml (autocomplete dropdown example) - Add Field Values Search - Genres.yml (autocomplete dropdown example) - Add Field Values Search - Series.yml (autocomplete dropdown example) - Add Field Values Search - Languages.yml (autocomplete dropdown example) - Remove deprecated Filter Media Items.yml scenario All files include request config, params, examples, expected responses, and success criteria for API interaction during development.
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
info:
|
||||||
|
name: Combined Search and Filters
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: q
|
||||||
|
value: "foundation"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: author_filter
|
||||||
|
value: "asimov"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: genre_filter
|
||||||
|
value: "scifi"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: year_min
|
||||||
|
value: "1950"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: year_max
|
||||||
|
value: "2000"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: sort
|
||||||
|
value: "title ASC"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Combined Search and Filters
|
||||||
|
|
||||||
|
Combines a search query with multiple filters to find specific media items.
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `q` (string, required): Search query for title/author/series/tags (fuzzy match)
|
||||||
|
- `author_filter` (string, optional): Fuzzy match author field
|
||||||
|
- `genre_filter` (string, optional): Fuzzy match genre field
|
||||||
|
- `year_min` (integer, optional): Minimum copyright year (exact match)
|
||||||
|
- `year_max` (integer, optional): Maximum copyright year (exact match)
|
||||||
|
- `sort` (string, optional): Sort order (e.g., "title ASC", "author DESC", "created_at DESC")
|
||||||
|
|
||||||
|
**How Combined Search Works:**
|
||||||
|
- All filters are AND'd together (must match ALL conditions)
|
||||||
|
- Search query (`q`) uses fuzzy matching across title, author, series, tags
|
||||||
|
- Text filters (author, genre) use fuzzy matching
|
||||||
|
- Year filters use exact range matching
|
||||||
|
- Results sorted by relevance first, then by sort parameter
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"title": "Foundation",
|
||||||
|
"author": "Asimov, Isaac",
|
||||||
|
"genre": "Sci-Fi",
|
||||||
|
"copyright_year": 1951,
|
||||||
|
"library_id": "uuid",
|
||||||
|
"library_name": "E-Books"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example Use Cases:**
|
||||||
|
- Find "Foundation" by "Asimov" in "Sci-Fi" genre from 1950-2000
|
||||||
|
- Search "potter" with genre "fantasy" published after 2000
|
||||||
|
- Find "mars" books by "sci-fi" authors sorted by date
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns items matching all filters
|
||||||
|
- Results sorted by relevance then by sort parameter
|
||||||
|
- Only returns items matching ALL specified conditions
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
info:
|
||||||
|
name: Exact Match With Quotes
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: q
|
||||||
|
value: "\"Foundation and Empire\""
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Exact Match With Quotes
|
||||||
|
|
||||||
|
Searches for an exact phrase match by wrapping the query in double quotes.
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `q` (string, required): Exact phrase to match (must be wrapped in double quotes)
|
||||||
|
|
||||||
|
**How Exact Match Works:**
|
||||||
|
- Wrap query in double quotes: `"\"exact phrase\""`
|
||||||
|
- Uses ILIKE pattern matching with wildcards
|
||||||
|
- Case-insensitive
|
||||||
|
- Must match the exact phrase (no fuzzy matching)
|
||||||
|
- Searches in: title, author, series, tags, contributors
|
||||||
|
|
||||||
|
**Fuzzy vs Exact Match:**
|
||||||
|
- Fuzzy (default): `asimov` → Matches "Asimov, Isaac", "Foundation and Asimov"
|
||||||
|
- Exact (with quotes): `"\"Asimov, Isaac\""` → Matches ONLY "Asimov, Isaac"
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"title": "Foundation and Empire",
|
||||||
|
"author": "Asimov, Isaac",
|
||||||
|
"library_id": "uuid",
|
||||||
|
"library_name": "E-Books"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `q="\"Foundation and Empire\""` → Only "Foundation and Empire" (not "Foundation")
|
||||||
|
- `q="\"The Hobbit\""` → Only "The Hobbit" (not "The Hobbit: There and Back Again")
|
||||||
|
- `q="\"J.R.R. Tolkien\""` → Only exact author name match
|
||||||
|
|
||||||
|
**When to Use Exact Match:**
|
||||||
|
- Searching for exact book titles in a series
|
||||||
|
- Finding specific edition or version
|
||||||
|
- Exact author name matching
|
||||||
|
- Preventing false positives from similar terms
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns items with exact phrase match
|
||||||
|
- No fuzzy matching applied
|
||||||
|
- Case-insensitive but must match exactly otherwise
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
info:
|
||||||
|
name: Field Values Search - Authors
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: author
|
||||||
|
value: "asimov"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: limit
|
||||||
|
value: "50"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Field Values Search - Authors
|
||||||
|
|
||||||
|
Fetches distinct author values for autocomplete dropdowns with counts and similarity scores.
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `author` (string, required): Author name to search for (fuzzy match)
|
||||||
|
- `limit` (integer, optional): Maximum results to return (default: 50)
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
- Returns distinct author names from the library
|
||||||
|
- Fuzzy matches the search query against author names
|
||||||
|
- Includes count of books per author
|
||||||
|
- Includes similarity score (0-1, higher = better match)
|
||||||
|
- Sorted by similarity score, then by count
|
||||||
|
|
||||||
|
**Use Case:**
|
||||||
|
- Populate autocomplete dropdown when user types in author filter field
|
||||||
|
- Show user available authors with book counts
|
||||||
|
- Help users discover similar author names
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"value": "Asimov, Isaac",
|
||||||
|
"count": 47,
|
||||||
|
"score": 0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Asimov, Isaac & Robert Silverberg",
|
||||||
|
"count": 2,
|
||||||
|
"score": 0.75
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `author=asimov` → Returns "Asimov, Isaac" (47 books), "Asimov, Isaac & Robert Silverberg" (2 books)
|
||||||
|
- `author=rowling` → Returns "Rowling, J.K." (10 books)
|
||||||
|
- `author=tolkien` → Returns "Tolkien, J.R.R." (15 books)
|
||||||
|
|
||||||
|
**Frontend Integration:**
|
||||||
|
- Call this endpoint when user types ≥2 characters in author field
|
||||||
|
- Display results in `<datalist>` or custom dropdown
|
||||||
|
- Show: "Author Name (count)" format
|
||||||
|
- Allow user to select from suggestions
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns array of author values with counts
|
||||||
|
- Results sorted by relevance (similarity score)
|
||||||
|
- Only returns authors matching the fuzzy search
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
info:
|
||||||
|
name: Field Values Search - Genres
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: genre
|
||||||
|
value: "sci"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: limit
|
||||||
|
value: "50"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Field Values Search - Genres
|
||||||
|
|
||||||
|
Fetches distinct genre values for autocomplete dropdowns with counts and similarity scores.
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `genre` (string, required): Genre name to search for (fuzzy match)
|
||||||
|
- `limit` (integer, optional): Maximum results to return (default: 50)
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
- Returns distinct genre names from the library
|
||||||
|
- Fuzzy matches the search query against genre names
|
||||||
|
- Includes count of books per genre
|
||||||
|
- Includes similarity score (0-1, higher = better match)
|
||||||
|
- Sorted by similarity score, then by count
|
||||||
|
|
||||||
|
**Use Case:**
|
||||||
|
- Populate autocomplete dropdown when user types in genre filter field
|
||||||
|
- Show user available genres with book counts
|
||||||
|
- Help users discover similar genre names
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"value": "Sci-Fi",
|
||||||
|
"count": 234,
|
||||||
|
"score": 0.85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Science Fiction",
|
||||||
|
"count": 156,
|
||||||
|
"score": 0.82
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `genre=sci` → Returns "Sci-Fi" (234 books), "Science Fiction" (156 books)
|
||||||
|
- `genre=fant` → Returns "Fantasy" (345 books), "High Fantasy" (89 books)
|
||||||
|
- `genre=mystery` → Returns "Mystery" (123 books), "Mystery/Thriller" (45 books)
|
||||||
|
|
||||||
|
**Frontend Integration:**
|
||||||
|
- Call this endpoint when user types ≥2 characters in genre field
|
||||||
|
- Display results in `<datalist>` or custom dropdown
|
||||||
|
- Show: "Genre Name (count)" format
|
||||||
|
- Allow user to select from suggestions
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns array of genre values with counts
|
||||||
|
- Results sorted by relevance (similarity score)
|
||||||
|
- Only returns genres matching the fuzzy search
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
info:
|
||||||
|
name: Field Values Search - Languages
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: language
|
||||||
|
value: "eng"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: limit
|
||||||
|
value: "50"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Field Values Search - Languages
|
||||||
|
|
||||||
|
Fetches distinct language values for autocomplete dropdowns with counts and similarity scores.
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `language` (string, required): Language name/code to search for (fuzzy match)
|
||||||
|
- `limit` (integer, optional): Maximum results to return (default: 50)
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
- Returns distinct language names from the library
|
||||||
|
- Fuzzy matches the search query against language names
|
||||||
|
- Includes count of books per language
|
||||||
|
- Includes similarity score (0-1, higher = better match)
|
||||||
|
- Sorted by similarity score, then by count
|
||||||
|
|
||||||
|
**Use Case:**
|
||||||
|
- Populate autocomplete dropdown when user types in language filter field
|
||||||
|
- Show user available languages with book counts
|
||||||
|
- Help users discover similar language codes/names
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"value": "English",
|
||||||
|
"count": 1245,
|
||||||
|
"score": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "eng",
|
||||||
|
"count": 856,
|
||||||
|
"score": 0.85
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `language=eng` → Returns "English" (1245 books), "eng" (856 books)
|
||||||
|
- `language=fre` → Returns "French" (234 books), "fre" (123 books)
|
||||||
|
- `language=german` → Returns "German" (189 books), "deutsch" (45 books)
|
||||||
|
|
||||||
|
**Frontend Integration:**
|
||||||
|
- Call this endpoint when user types ≥2 characters in language field
|
||||||
|
- Display results in `<datalist>` or custom dropdown
|
||||||
|
- Show: "Language Name (count)" format
|
||||||
|
- Allow user to select from suggestions
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns array of language values with counts
|
||||||
|
- Results sorted by relevance (similarity score)
|
||||||
|
- Only returns languages matching the fuzzy search
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
info:
|
||||||
|
name: Field Values Search - Series
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: series
|
||||||
|
value: "foundation"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: limit
|
||||||
|
value: "50"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Field Values Search - Series
|
||||||
|
|
||||||
|
Fetches distinct series values for autocomplete dropdowns with counts and similarity scores.
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `series` (string, required): Series name to search for (fuzzy match)
|
||||||
|
- `limit` (integer, optional): Maximum results to return (default: 50)
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
- Returns distinct series names from the library
|
||||||
|
- Fuzzy matches the search query against series names
|
||||||
|
- Includes count of books per series
|
||||||
|
- Includes similarity score (0-1, higher = better match)
|
||||||
|
- Sorted by similarity score, then by count
|
||||||
|
|
||||||
|
**Use Case:**
|
||||||
|
- Populate autocomplete dropdown when user types in series filter field
|
||||||
|
- Show user available series with book counts
|
||||||
|
- Help users discover similar series names
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"value": "Foundation",
|
||||||
|
"count": 7,
|
||||||
|
"score": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "Foundation Series",
|
||||||
|
"count": 7,
|
||||||
|
"score": 0.85
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `series=foundation` → Returns "Foundation" (7 books), "Foundation Series" (7 books)
|
||||||
|
- `series=harry` → Returns "Harry Potter" (10 books)
|
||||||
|
- `series=lord` → Returns "Lord of the Rings" (3 books)
|
||||||
|
|
||||||
|
**Frontend Integration:**
|
||||||
|
- Call this endpoint when user types ≥2 characters in series field
|
||||||
|
- Display results in `<datalist>` or custom dropdown
|
||||||
|
- Show: "Series Name (count)" format
|
||||||
|
- Allow user to select from suggestions
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns array of series values with counts
|
||||||
|
- Results sorted by relevance (similarity score)
|
||||||
|
- Only returns series matching the fuzzy search
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
info:
|
||||||
|
name: Fuzzy Author Filter
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: author_filter
|
||||||
|
value: "asimov"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Fuzzy Author Filter
|
||||||
|
|
||||||
|
Filters media items by author using fuzzy matching (tolerates typos).
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `author_filter` (string, required): Author name to fuzzy match (e.g., "asimov" matches "Asimov, Isaac")
|
||||||
|
|
||||||
|
**How Fuzzy Matching Works:**
|
||||||
|
- Uses PostgreSQL pg_trgm word_similarity()
|
||||||
|
- Threshold: 0.3 (30% similarity)
|
||||||
|
- Handles typos: "azimov" → "Asimov"
|
||||||
|
- Handles partial matches: "asimov" → "Asimov, Isaac"
|
||||||
|
- Case-insensitive
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"title": "Foundation",
|
||||||
|
"author": "Asimov, Isaac",
|
||||||
|
"library_id": "uuid",
|
||||||
|
"library_name": "E-Books"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `author_filter=asimov` → Matches "Asimov, Isaac", "Asimov, Isaac & Robert Silverberg"
|
||||||
|
- `author_filter=rowling` → Matches "Rowling, J.K."
|
||||||
|
- `author_filter=tolkien` → Matches "Tolkien, J.R.R."
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns items with authors similar to the filter
|
||||||
|
- Results sorted by similarity score
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
info:
|
||||||
|
name: Fuzzy Genre Filter
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
url: "{{base_url}}/api/media-items/search"
|
||||||
|
params:
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: genre_filter
|
||||||
|
value: "scifi"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
||||||
|
docs: |-
|
||||||
|
## Fuzzy Genre Filter
|
||||||
|
|
||||||
|
Filters media items by genre using fuzzy matching (tolerates typos and variations).
|
||||||
|
|
||||||
|
**Method:** GET
|
||||||
|
|
||||||
|
**Endpoint:** /api/media-items/search
|
||||||
|
|
||||||
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `library_id` (string, required): Library UUID to search within
|
||||||
|
- `genre_filter` (string, required): Genre to fuzzy match (e.g., "scifi" matches "Sci-Fi", "Science Fiction")
|
||||||
|
|
||||||
|
**How Fuzzy Matching Works:**
|
||||||
|
- Uses PostgreSQL pg_trgm word_similarity()
|
||||||
|
- Threshold: 0.3 (30% similarity)
|
||||||
|
- Handles variations: "scifi" → "Sci-Fi", "Science Fiction"
|
||||||
|
- Handles typos: "fantacy" → "Fantasy"
|
||||||
|
- Case-insensitive
|
||||||
|
|
||||||
|
**Response:** HTTP 200 (OK)
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"title": "Foundation",
|
||||||
|
"author": "Asimov, Isaac",
|
||||||
|
"genre": "Sci-Fi",
|
||||||
|
"library_id": "uuid",
|
||||||
|
"library_name": "E-Books"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `genre_filter=scifi` → Matches "Sci-Fi", "Science Fiction"
|
||||||
|
- `genre_filter=fantasy` → Matches "Fantasy", "High Fantasy"
|
||||||
|
- `genre_filter=mystery` → Matches "Mystery", "Mystery/Thriller"
|
||||||
|
|
||||||
|
**Success Criteria:**
|
||||||
|
- Status: 200
|
||||||
|
- Returns items with genres similar to the filter
|
||||||
|
- Results sorted by similarity score
|
||||||
@@ -8,9 +8,53 @@ http:
|
|||||||
url: "{{base_url}}/api/media-items/search"
|
url: "{{base_url}}/api/media-items/search"
|
||||||
params:
|
params:
|
||||||
- name: q
|
- name: q
|
||||||
value: "harry"
|
value: "foundation"
|
||||||
type: query
|
type: query
|
||||||
disabled: false
|
disabled: false
|
||||||
|
- name: library_id
|
||||||
|
value: "{{library_id}}"
|
||||||
|
type: query
|
||||||
|
disabled: false
|
||||||
|
- name: author_filter
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: series_filter
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: genre_filter
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: language_filter
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: year_min
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: year_max
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: has_cover
|
||||||
|
value: ""
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: sort
|
||||||
|
value: "title ASC"
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: limit
|
||||||
|
value: "50"
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
|
- name: offset
|
||||||
|
value: "0"
|
||||||
|
type: query
|
||||||
|
disabled: true
|
||||||
auth: inherit
|
auth: inherit
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
@@ -22,7 +66,7 @@ settings:
|
|||||||
docs: |-
|
docs: |-
|
||||||
## Search All Libraries
|
## Search All Libraries
|
||||||
|
|
||||||
Searches for media items across all libraries without filtering.
|
Searches for media items using the unified search endpoint. Supports fuzzy search, exact match, and filtering.
|
||||||
|
|
||||||
**Method:** GET
|
**Method:** GET
|
||||||
|
|
||||||
@@ -30,23 +74,148 @@ docs: |-
|
|||||||
|
|
||||||
**Authentication:** Required (Bearer token)
|
**Authentication:** Required (Bearer token)
|
||||||
|
|
||||||
**Query Parameters:**
|
## Query Parameters
|
||||||
- `q` (string, required): Search query (minimum 2 characters)
|
|
||||||
|
|
||||||
**Response:** HTTP 200 (OK)
|
### Search Parameters:
|
||||||
|
- `q` (string, optional): Global search query
|
||||||
|
- Fuzzy matching by default (tolerates typos)
|
||||||
|
- Exact match with quotes: `"\"exact phrase\""`
|
||||||
|
- Searches: title, author, series, tags, contributors
|
||||||
|
- Example: `q=foundation` (fuzzy), `q="\"Foundation and Empire\""` (exact)
|
||||||
|
|
||||||
|
### Filter Parameters (All Fuzzy Except Years/Booleans):
|
||||||
|
- `author_filter` (string, optional): Fuzzy match author field
|
||||||
|
- Example: `author_filter=asimov` matches "Asimov, Isaac"
|
||||||
|
|
||||||
|
- `series_filter` (string, optional): Fuzzy match series field
|
||||||
|
- Example: `series_filter=harry` matches "Harry Potter"
|
||||||
|
|
||||||
|
- `genre_filter` (string, optional): Fuzzy match genre field
|
||||||
|
- Example: `genre_filter=scifi` matches "Sci-Fi", "Science Fiction"
|
||||||
|
|
||||||
|
- `language_filter` (string, optional): Fuzzy match language field
|
||||||
|
- Example: `language_filter=eng` matches "English", "eng"
|
||||||
|
|
||||||
|
- `year_min` (integer, optional): Minimum copyright year (exact range)
|
||||||
|
- Example: `year_min=2000`
|
||||||
|
|
||||||
|
- `year_max` (integer, optional): Maximum copyright year (exact range)
|
||||||
|
- Example: `year_max=2020`
|
||||||
|
|
||||||
|
- `has_cover` (boolean, optional): Filter by cover image presence
|
||||||
|
- Values: `true`, `false`, or empty (all)
|
||||||
|
- Example: `has_cover=true`
|
||||||
|
|
||||||
|
### Pagination Parameters:
|
||||||
|
- `limit` (integer, optional): Number of results (default: 50, max: 200)
|
||||||
|
- Example: `limit=100`
|
||||||
|
|
||||||
|
- `offset` (integer, optional): Number of results to skip (for pagination)
|
||||||
|
- Example: `offset=50`
|
||||||
|
|
||||||
|
- `sort` (string, optional): Sort order (default: relevance DESC, title ASC)
|
||||||
|
- Options:
|
||||||
|
- `title ASC` - Title A-Z
|
||||||
|
- `title DESC` - Title Z-A
|
||||||
|
- `author ASC` - Author A-Z
|
||||||
|
- `author DESC` - Author Z-A
|
||||||
|
- `created_at ASC` - Date added oldest first
|
||||||
|
- `created_at DESC` - Date added newest first
|
||||||
|
- `page_count ASC` - Page count low to high
|
||||||
|
- `page_count DESC` - Page count high to low
|
||||||
|
- Example: `sort=author ASC`
|
||||||
|
|
||||||
|
## How Fuzzy Matching Works
|
||||||
|
|
||||||
|
**Text Filters (author, series, genre, language):**
|
||||||
|
- Uses PostgreSQL pg_trgm word_similarity()
|
||||||
|
- Threshold: 0.3 (30% similarity)
|
||||||
|
- Handles typos: "azimov" → "Asimov"
|
||||||
|
- Handles partial matches: "scifi" → "Sci-Fi"
|
||||||
|
- Case-insensitive
|
||||||
|
|
||||||
|
**Search Query (q parameter):**
|
||||||
|
- **Fuzzy (default):** Matches similar words across title, author, series, tags
|
||||||
|
- `q=foundation` → "Foundation", "Foundations", "The Foundation"
|
||||||
|
- **Exact (with quotes):** Must match the exact phrase
|
||||||
|
- `q="\"Foundation and Empire\""` → Only "Foundation and Empire"
|
||||||
|
|
||||||
|
## Response
|
||||||
|
|
||||||
|
**HTTP 200 (OK):**
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": "uuid",
|
"id": "uuid",
|
||||||
"title": "Harry Potter and the Sorcerer's Stone",
|
"title": "Foundation",
|
||||||
"author": "J.K. Rowling",
|
"author": "Asimov, Isaac",
|
||||||
|
"series": "Foundation",
|
||||||
|
"genre": "Sci-Fi",
|
||||||
|
"language": "English",
|
||||||
|
"copyright_year": 1951,
|
||||||
|
"page_count": 255,
|
||||||
|
"cover_image_path": "/path/to/cover.jpg",
|
||||||
"library_id": "uuid",
|
"library_id": "uuid",
|
||||||
"library_name": "E-Books"
|
"library_name": "E-Books",
|
||||||
|
"library_type_name": "ebooks"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
**Success Criteria:**
|
**HTTP 404 (Not Found):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "no results found",
|
||||||
|
"query": "foundation",
|
||||||
|
"results": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
**1. Simple search:**
|
||||||
|
```
|
||||||
|
GET /api/media-items/search?q=harry&library_id={uuid}
|
||||||
|
```
|
||||||
|
Returns books matching "harry" in title/author/series
|
||||||
|
|
||||||
|
**2. Fuzzy author filter:**
|
||||||
|
```
|
||||||
|
GET /api/media-items/search?author_filter=asimov&library_id={uuid}
|
||||||
|
```
|
||||||
|
Returns books by authors similar to "asimov"
|
||||||
|
|
||||||
|
**3. Combined search + filters:**
|
||||||
|
```
|
||||||
|
GET /api/media-items/search?q=foundation&author_filter=asimov&genre_filter=scifi&library_id={uuid}
|
||||||
|
```
|
||||||
|
Returns "foundation" books by "asimov" in "scifi" genre
|
||||||
|
|
||||||
|
**4. Exact match with quotes:**
|
||||||
|
```
|
||||||
|
GET /api/media-items/search?q="\"Foundation and Empire\""&library_id={uuid}
|
||||||
|
```
|
||||||
|
Returns only exact title match
|
||||||
|
|
||||||
|
**5. Year range + sorting:**
|
||||||
|
```
|
||||||
|
GET /api/media-items/search?year_min=2000&year_max=2020&sort=created_at DESC&library_id={uuid}
|
||||||
|
```
|
||||||
|
Returns books from 2000-2020 sorted by newest first
|
||||||
|
|
||||||
|
**6. Boolean filter:**
|
||||||
|
```
|
||||||
|
GET /api/media-items/search?has_cover=true&library_id={uuid}
|
||||||
|
```
|
||||||
|
Returns only books that have cover images
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
- Status: 200
|
- Status: 200
|
||||||
- Returns array of media items from all libraries
|
- Returns array of media items matching all filters
|
||||||
- Results match search query
|
- Results sorted by:
|
||||||
|
1. Relevance score (when searching with `q`)
|
||||||
|
2. User-specified sort parameter
|
||||||
|
3. Title (final fallback)
|
||||||
|
- Pagination works correctly with limit/offset
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
info:
|
|
||||||
name: Filter Media Items
|
|
||||||
type: http
|
|
||||||
seq: 1
|
|
||||||
http:
|
|
||||||
method: GET
|
|
||||||
url: '{{base_url}}/api/media-items/filtered?library_id={{library_id}}&genre_filter=Fiction&language_filter=en&year_min=2000&year_max=2024&limit=10&offset=0'
|
|
||||||
auth: inherit
|
|
||||||
body:
|
|
||||||
type: none
|
|
||||||
headers:
|
|
||||||
- key: Content-Type
|
|
||||||
value: application/json
|
|
||||||
|
|
||||||
docs: |-
|
|
||||||
## Filter Media Items
|
|
||||||
|
|
||||||
**Method:** GET
|
|
||||||
|
|
||||||
**Endpoint:** /api/media-items/filtered
|
|
||||||
|
|
||||||
**Authentication:** Required (Bearer token)
|
|
||||||
|
|
||||||
**Query Parameters:**
|
|
||||||
- `library_id` (string, required): UUID of the library
|
|
||||||
- `author_filter` (string, optional): Filter by author (partial match)
|
|
||||||
- `series_filter` (string, optional): Filter by series (partial match)
|
|
||||||
- `genre_filter` (string, optional): Filter by genre (exact match)
|
|
||||||
- `language_filter` (string, optional): Filter by language (exact match, e.g., 'en', 'es', 'fr')
|
|
||||||
- `year_min` (integer, optional): Minimum copyright year
|
|
||||||
- `year_max` (integer, optional): Maximum copyright year
|
|
||||||
- `has_cover` (boolean, optional): Filter for items with cover images only
|
|
||||||
- `sort` (string, optional): Sort field and direction (same options as ListMediaItems)
|
|
||||||
- `limit` (integer, optional): Number of items to return (default: 50, max: 1000)
|
|
||||||
- `offset` (integer, optional): Number of items to skip (default: 0)
|
|
||||||
|
|
||||||
**Response:** Object containing array of filtered media items
|
|
||||||
|
|
||||||
**Status Codes:**
|
|
||||||
- 200: Success
|
|
||||||
- 400: Bad request (invalid parameters)
|
|
||||||
- 401: Unauthorized
|
|
||||||
- 500: Internal server error
|
|
||||||
|
|
||||||
**Examples:**
|
|
||||||
- Filter by genre: `/api/media-items/filtered?library_id=xxx&genre_filter=Fiction`
|
|
||||||
- Filter by language: `/api/media-items/filtered?library_id=xxx&language_filter=es`
|
|
||||||
- Filter by year range: `/api/media-items/filtered?library_id=xxx&year_min=2000&year_max=2024`
|
|
||||||
- Filter by cover: `/api/media-items/filtered?library_id=xxx&has_cover=true`
|
|
||||||
- Combine filters: `/api/media-items/filtered?library_id=xxx&genre_filter=Sci-Fi&year_min=2010&language_filter=en`
|
|
||||||
|
|
||||||
**Filter Behavior:**
|
|
||||||
- Multiple filters can be combined (AND logic)
|
|
||||||
- Author and series filters use partial matching (ILIKE)
|
|
||||||
- Genre and language filters use exact matching
|
|
||||||
- Year range filters are inclusive
|
|
||||||
- Filters are applied before sorting and pagination
|
|
||||||
- User library visibility is respected
|
|
||||||
Reference in New Issue
Block a user