feat: modify the response format for search

This commit is contained in:
Phan An 2020-12-25 12:52:28 +01:00
parent cacca23c02
commit 588b30d9bb
4 changed files with 118 additions and 25 deletions

View file

@ -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

View file

@ -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),
];
}
}

View file

@ -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')),
];
}
}

View file

@ -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;
});
}
}