refactor: reorganize Bruno API collection into subdirectories
- Move search-related requests into bruno/media-items/search/ subdirectory - Rename Fuzzy Genre Filter.yml to Fuzzy Tags Filter.yml - Keep scenario-based requests in bruno/media-items/scenarios/ - Improve collection organization and discoverability This reorganization makes the Bruno API collection more organized by grouping search endpoints together and updating genre filter to tags filter.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
info:
|
||||
name: Combined Search and Filters
|
||||
type: http
|
||||
seq: 1
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&q=foundation&author_filter=asimov&tags_filter=scifi&year_min=1950&year_max=2000&sort=title ASC"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: q
|
||||
value: foundation
|
||||
type: query
|
||||
- name: author_filter
|
||||
value: asimov
|
||||
type: query
|
||||
- name: tags_filter
|
||||
value: scifi
|
||||
type: query
|
||||
- name: year_min
|
||||
value: "1950"
|
||||
type: query
|
||||
- name: year_max
|
||||
value: "2000"
|
||||
type: query
|
||||
- name: sort
|
||||
value: title ASC
|
||||
type: query
|
||||
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
|
||||
- `tags_filter` (string, optional): Fuzzy match tags 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, tags) 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",
|
||||
"tags": "Sci-Fi",
|
||||
"copyright_year": 1951,
|
||||
"library_id": "uuid",
|
||||
"library_name": "E-Books"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Example Use Cases:**
|
||||
- Find "Foundation" by "Asimov" in "Sci-Fi" tags from 1950-2000
|
||||
- Search "potter" with tags "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,78 @@
|
||||
info:
|
||||
name: Exact Match With Quotes
|
||||
type: http
|
||||
seq: 5
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/media-items/search?library_id={{library_id}}&q="Foundation and Empire"'
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: q
|
||||
value: '"Foundation and Empire"'
|
||||
type: query
|
||||
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,89 @@
|
||||
info:
|
||||
name: Field Values Search - Authors
|
||||
type: http
|
||||
seq: 6
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&author=asimov&limit=50"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: author
|
||||
value: asimov
|
||||
type: query
|
||||
- name: limit
|
||||
value: "50"
|
||||
type: query
|
||||
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,89 @@
|
||||
info:
|
||||
name: Field Values Search - Genres
|
||||
type: http
|
||||
seq: 7
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&tags=sci&limit=50"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: tags
|
||||
value: sci
|
||||
type: query
|
||||
- name: limit
|
||||
value: "50"
|
||||
type: query
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
## Field Values Search - Genres
|
||||
|
||||
Fetches distinct tags 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
|
||||
- `tags` (string, required): Genre name to search for (fuzzy match)
|
||||
- `limit` (integer, optional): Maximum results to return (default: 50)
|
||||
|
||||
**How It Works:**
|
||||
- Returns distinct tags names from the library
|
||||
- Fuzzy matches the search query against tags names
|
||||
- Includes count of books per tags
|
||||
- Includes similarity score (0-1, higher = better match)
|
||||
- Sorted by similarity score, then by count
|
||||
|
||||
**Use Case:**
|
||||
- Populate autocomplete dropdown when user types in tags filter field
|
||||
- Show user available tagss with book counts
|
||||
- Help users discover similar tags 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:**
|
||||
- `tags=sci` → Returns "Sci-Fi" (234 books), "Science Fiction" (156 books)
|
||||
- `tags=fant` → Returns "Fantasy" (345 books), "High Fantasy" (89 books)
|
||||
- `tags=mystery` → Returns "Mystery" (123 books), "Mystery/Thriller" (45 books)
|
||||
|
||||
**Frontend Integration:**
|
||||
- Call this endpoint when user types ≥2 characters in tags 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 tags values with counts
|
||||
- Results sorted by relevance (similarity score)
|
||||
- Only returns tagss matching the fuzzy search
|
||||
@@ -0,0 +1,89 @@
|
||||
info:
|
||||
name: Field Values Search - Languages
|
||||
type: http
|
||||
seq: 8
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&language=eng&limit=50"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: language
|
||||
value: eng
|
||||
type: query
|
||||
- name: limit
|
||||
value: "50"
|
||||
type: query
|
||||
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,89 @@
|
||||
info:
|
||||
name: Field Values Search - Series
|
||||
type: http
|
||||
seq: 9
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&series=foundation&limit=50"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: series
|
||||
value: foundation
|
||||
type: query
|
||||
- name: limit
|
||||
value: "50"
|
||||
type: query
|
||||
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,67 @@
|
||||
info:
|
||||
name: Fuzzy Author Filter
|
||||
type: http
|
||||
seq: 10
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&author_filter=Conan"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: author_filter
|
||||
value: Conan
|
||||
type: query
|
||||
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,68 @@
|
||||
info:
|
||||
name: Fuzzy Genre Filter
|
||||
type: http
|
||||
seq: 11
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?library_id={{library_id}}&tags_filter=scifi"
|
||||
params:
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: tags_filter
|
||||
value: scifi
|
||||
type: query
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
## Fuzzy Genre Filter
|
||||
|
||||
Filters media items by tags 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
|
||||
- `tags_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",
|
||||
"tags": "Sci-Fi",
|
||||
"library_id": "uuid",
|
||||
"library_name": "E-Books"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
- `tags_filter=scifi` → Matches "Sci-Fi", "Science Fiction"
|
||||
- `tags_filter=fantasy` → Matches "Fantasy", "High Fantasy"
|
||||
- `tags_filter=mystery` → Matches "Mystery", "Mystery/Thriller"
|
||||
|
||||
**Success Criteria:**
|
||||
- Status: 200
|
||||
- Returns items with tagss similar to the filter
|
||||
- Results sorted by similarity score
|
||||
@@ -0,0 +1,218 @@
|
||||
info:
|
||||
name: Search All Libraries
|
||||
type: http
|
||||
seq: 13
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?q=foundation&library_id={{library_id}}"
|
||||
params:
|
||||
- name: q
|
||||
value: foundation
|
||||
type: query
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
- name: author_filter
|
||||
value: ""
|
||||
type: query
|
||||
disabled: true
|
||||
- name: series_filter
|
||||
value: ""
|
||||
type: query
|
||||
disabled: true
|
||||
- name: tags_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
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
## Search All Libraries
|
||||
|
||||
Searches for media items using the unified search endpoint. Supports fuzzy search, exact match, and filtering.
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**Endpoint:** /api/media-items/search
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
## Query Parameters
|
||||
|
||||
### 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"
|
||||
|
||||
- `tags_filter` (string, optional): Fuzzy match tags field
|
||||
- Example: `tags_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, tags, 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
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "Foundation",
|
||||
"author": "Asimov, Isaac",
|
||||
"series": "Foundation",
|
||||
"tags": "Sci-Fi",
|
||||
"language": "English",
|
||||
"copyright_year": 1951,
|
||||
"page_count": 255,
|
||||
"cover_image_path": "/path/to/cover.jpg",
|
||||
"library_id": "uuid",
|
||||
"library_name": "E-Books",
|
||||
"library_type_name": "ebooks"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**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&tags_filter=scifi&library_id={uuid}
|
||||
```
|
||||
Returns "foundation" books by "asimov" in "scifi" tags
|
||||
|
||||
**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
|
||||
- Returns array of media items matching all filters
|
||||
- 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
|
||||
@@ -0,0 +1,58 @@
|
||||
info:
|
||||
name: Search Specific Library
|
||||
type: http
|
||||
seq: 15
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/media-items/search?q=beo&library_id={{library_id}}"
|
||||
params:
|
||||
- name: q
|
||||
value: beo
|
||||
type: query
|
||||
- name: library_id
|
||||
value: "{{library_id}}"
|
||||
type: query
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
## Search Specific Library
|
||||
|
||||
Searches for media items within a specific library using the library_id filter.
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**Endpoint:** /api/media-items/search
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Query Parameters:**
|
||||
- `q` (string, required): Search query (minimum 2 characters)
|
||||
- `library_id` (string/UUID, required): Filter results to specific library
|
||||
|
||||
**Response:** HTTP 200 (OK)
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"title": "Harry Potter and the Sorcerer's Stone",
|
||||
"author": "J.K. Rowling",
|
||||
"library_id": "{{libraryId}}",
|
||||
"library_name": "My Library"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Success Criteria:**
|
||||
- Status: 200
|
||||
- All results have `library_id` matching the filter
|
||||
- Results match search query
|
||||
|
||||
**Test Setup:**
|
||||
- Set `libraryId` environment variable to a valid library UUID
|
||||
Reference in New Issue
Block a user