mirror of
https://github.com/koel/koel
synced 2024-11-24 05:03:05 +00:00
feat: modify the response format for search
This commit is contained in:
parent
cacca23c02
commit
588b30d9bb
4 changed files with 118 additions and 25 deletions
|
@ -2,7 +2,7 @@ openapi: 3.0.0
|
|||
info:
|
||||
title: Koel API
|
||||
version: 5.0.0
|
||||
description: 'The API for [Koel](http://koel.dev), the music streaming application that works.'
|
||||
description: 'The API for [Koel](https://koel.dev), the music streaming application that works.'
|
||||
contact:
|
||||
name: An Phan
|
||||
url: 'https://phanan.net'
|
||||
|
@ -11,7 +11,7 @@ info:
|
|||
name: MIT
|
||||
url: 'https://github.com/koel/koel/blob/master/LICENSE.md'
|
||||
servers:
|
||||
- url: 'http://localhost:8000'
|
||||
- url: 'https://koel.test'
|
||||
description: Local
|
||||
tags:
|
||||
- name: interaction
|
||||
|
@ -852,8 +852,7 @@ paths:
|
|||
$ref: '#/components/schemas/Song'
|
||||
operationId: post-os-s3-song
|
||||
description: Create a new song or update an existing one with data sent from AWS
|
||||
security:
|
||||
- appKey: []
|
||||
security: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
|
@ -908,8 +907,7 @@ paths:
|
|||
'204':
|
||||
description: No Content
|
||||
description: Remove a song whose information matches the data sent from AWS S3 (`bucket` and `key`)
|
||||
security:
|
||||
- appKey: []
|
||||
security: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
|
@ -1103,6 +1101,84 @@ paths:
|
|||
description: Download a whole playlist. This is NOT an XmlHttpRequest. The response will be a download response of either one media file or a zip file containg multiple media files.
|
||||
security:
|
||||
- api-token: []
|
||||
/api/search:
|
||||
get:
|
||||
summary: 'Search for songs, albums, and artists'
|
||||
tags:
|
||||
- search
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
results:
|
||||
type: object
|
||||
required:
|
||||
- songs
|
||||
- artists
|
||||
- albums
|
||||
properties:
|
||||
songs:
|
||||
type: array
|
||||
description: An array of max 6 best-matching songs' IDs
|
||||
items:
|
||||
type: string
|
||||
artists:
|
||||
type: array
|
||||
description: An array of max 6 best-matching artists' IDs
|
||||
items:
|
||||
type: integer
|
||||
albums:
|
||||
type: array
|
||||
description: An array of max 6 best-matching albums' IDs
|
||||
items:
|
||||
type: number
|
||||
required:
|
||||
- results
|
||||
operationId: get-api-search
|
||||
description: 'Seach for songs, albums, and artists, with a maximum of {count} results each.'
|
||||
security:
|
||||
- Bearer Token: []
|
||||
parameters:
|
||||
- schema:
|
||||
type: string
|
||||
in: query
|
||||
name: q
|
||||
description: The keywords to search
|
||||
required: true
|
||||
- schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
default: 6
|
||||
in: query
|
||||
name: count
|
||||
description: 'The maximum number of results for songs, artists, and albums'
|
||||
parameters: []
|
||||
/api/search/songs:
|
||||
get:
|
||||
summary: Search for songs
|
||||
tags:
|
||||
- search
|
||||
responses: {}
|
||||
operationId: get-api-search-songs
|
||||
description: Get all songs that matches a search query.
|
||||
security:
|
||||
- Bearer Token: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
songs:
|
||||
type: array
|
||||
description: An array of matching songs' IDs
|
||||
items: {}
|
||||
required:
|
||||
- songs
|
||||
components:
|
||||
schemas:
|
||||
User:
|
||||
|
@ -1638,10 +1714,6 @@ components:
|
|||
Bearer Token:
|
||||
type: http
|
||||
scheme: bearer
|
||||
appKey:
|
||||
name: The applcation key (APP_KEY in .env)
|
||||
type: apiKey
|
||||
in: query
|
||||
api-token:
|
||||
name: The API token as a query parameter
|
||||
type: apiKey
|
|
@ -22,8 +22,14 @@ class ExcerptSearchController extends Controller
|
|||
throw new InvalidArgumentException('A search query is required.');
|
||||
}
|
||||
|
||||
$count = (int) $request->get('count', SearchService::DEFAULT_EXCERPT_RESULT_COUNT);
|
||||
|
||||
if ($count < 0) {
|
||||
throw new InvalidArgumentException('Invalid count parameter.');
|
||||
}
|
||||
|
||||
return [
|
||||
'results' => $this->searchService->excerptSearch($request->get('q')),
|
||||
'results' => $this->searchService->excerptSearch($request->get('q'), $count),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Controllers\API\Search;
|
||||
|
||||
use App\Http\Controllers\API\Controller;
|
||||
use App\Models\Song;
|
||||
use App\Services\SearchService;
|
||||
use Illuminate\Http\Request;
|
||||
use InvalidArgumentException;
|
||||
|
@ -24,11 +23,7 @@ class SongSearchController extends Controller
|
|||
}
|
||||
|
||||
return [
|
||||
'songs' => $this->searchService->searchSongs($request->get('q'))
|
||||
->get()
|
||||
->map(static function (Song $song): string {
|
||||
return $song->id;
|
||||
}),
|
||||
'songs' => $this->searchService->searchSongs($request->get('q')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,20 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Album;
|
||||
use App\Models\Artist;
|
||||
use App\Models\Song;
|
||||
use App\Repositories\AlbumRepository;
|
||||
use App\Repositories\ArtistRepository;
|
||||
use App\Repositories\SongRepository;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Scout\Builder;
|
||||
|
||||
class SearchService
|
||||
{
|
||||
public const DEFAULT_EXCERPT_RESULT_COUNT = 6;
|
||||
|
||||
private $songRepository;
|
||||
private $albumRepository;
|
||||
private $artistRepository;
|
||||
|
@ -26,23 +31,38 @@ class SearchService
|
|||
}
|
||||
|
||||
/** @return array<mixed> */
|
||||
public function excerptSearch(string $keywords): array
|
||||
public function excerptSearch(string $keywords, int $count): array
|
||||
{
|
||||
return [
|
||||
'songs' => self::getTopResults($this->songRepository->search($keywords)),
|
||||
'artists' => self::getTopResults($this->artistRepository->search($keywords)),
|
||||
'albums' => self::getTopResults($this->albumRepository->search($keywords)),
|
||||
'songs' => self::getTopResults($this->songRepository->search($keywords), $count)
|
||||
->map(static function (Song $song): string {
|
||||
return $song->id;
|
||||
}),
|
||||
'artists' => self::getTopResults($this->artistRepository->search($keywords), $count)
|
||||
->map(static function (Artist $artist): int {
|
||||
return $artist->id;
|
||||
}),
|
||||
'albums' => self::getTopResults($this->albumRepository->search($keywords), $count)
|
||||
->map(static function (Album $album): int {
|
||||
return $album->id;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return Collection|array<Model> */
|
||||
private static function getTopResults(Builder $query, int $count = 6): Collection
|
||||
private static function getTopResults(Builder $query, int $count): Collection
|
||||
{
|
||||
return $query->take($count)->get();
|
||||
}
|
||||
|
||||
public function searchSongs(string $keywords): Builder
|
||||
/** @return Collection|array<string> */
|
||||
public function searchSongs(string $keywords): Collection
|
||||
{
|
||||
return $this->songRepository->search($keywords);
|
||||
return $this->songRepository
|
||||
->search($keywords)
|
||||
->get()
|
||||
->map(static function (Song $song): string {
|
||||
return $song->id;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue