mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
improved full-text search
- added support for typesense 0.24.1 - fixed issue where empty `filter_by` field being sent to typesense which resulted in an error - added infix indexing for title fields in case of Anime/Manga - added more env vars for customising typesense search - upgraded typesense driver
This commit is contained in:
parent
6eff2af172
commit
dc9b234f19
@ -273,6 +273,70 @@ class Anime extends JikanApiSearchableModel
|
||||
];
|
||||
}
|
||||
|
||||
public function getCollectionSchema(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->searchableAs(),
|
||||
'fields' => [
|
||||
[
|
||||
'name' => '.*',
|
||||
'type' => 'auto',
|
||||
],
|
||||
[
|
||||
'name' => 'title',
|
||||
'type' => 'string',
|
||||
'optional' => false,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_transformed',
|
||||
'type' => 'string',
|
||||
'optional' => false,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_japanese',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'locale' => 'jp',
|
||||
'infix' => true,
|
||||
'sort' => false
|
||||
],
|
||||
[
|
||||
'name' => 'title_japanese_transformed',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'locale' => 'jp',
|
||||
'infix' => true,
|
||||
'sort' => false
|
||||
],
|
||||
[
|
||||
'name' => 'title_english',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_english_transformed',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_synonyms',
|
||||
'type' => 'string[]',
|
||||
'optional' => true,
|
||||
'infix' => true,
|
||||
'sort' => false
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The fields to be queried against. See https://typesense.org/docs/0.21.0/api/documents.html#search.
|
||||
*
|
||||
|
@ -3,8 +3,10 @@
|
||||
namespace App\Features;
|
||||
|
||||
use App\Dto\AnimeSearchCommand;
|
||||
use App\Enums\AnimeOrderByEnum;
|
||||
use App\Http\Resources\V4\AnimeCollection;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* @extends SearchRequestHandler<AnimeSearchCommand, AnimeCollection>
|
||||
@ -23,4 +25,14 @@ class AnimeSearchHandler extends SearchRequestHandler
|
||||
{
|
||||
return new AnimeCollection($paginator);
|
||||
}
|
||||
|
||||
protected function prepareOrderByParam(Collection $requestData): Collection
|
||||
{
|
||||
if ($requestData->has("q") && !$requestData->has("order_by")) {
|
||||
// default order by should be popularity, as MAL seems to use this trick.
|
||||
$requestData->offsetSet("order_by", AnimeOrderByEnum::popularity());
|
||||
}
|
||||
|
||||
return parent::prepareOrderByParam($requestData);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,10 @@
|
||||
namespace App\Features;
|
||||
|
||||
use App\Dto\MangaSearchCommand;
|
||||
use App\Enums\MangaOrderByEnum;
|
||||
use App\Http\Resources\V4\MangaCollection;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* @extends SearchRequestHandler<MangaSearchCommand, MangaCollection>
|
||||
@ -26,4 +28,14 @@ class MangaSearchHandler extends SearchRequestHandler
|
||||
{
|
||||
return new MangaCollection($paginator);
|
||||
}
|
||||
|
||||
protected function prepareOrderByParam(Collection $requestData): Collection
|
||||
{
|
||||
if ($requestData->has("q") && !$requestData->has("order_by")) {
|
||||
// default order by should be popularity, as MAL seems to use this trick.
|
||||
$requestData->offsetSet("order_by", MangaOrderByEnum::popularity());
|
||||
}
|
||||
|
||||
return parent::prepareOrderByParam($requestData);
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ abstract class SearchRequestHandler implements RequestHandler
|
||||
if ($requestData->has('order_by') && $requestData->has('q')) {
|
||||
$requestData->offsetSet("order_by", $requestData->get("order_by")->label);
|
||||
return $requestData;
|
||||
|
||||
}
|
||||
|
||||
$requestData->offsetSet("order_by", 'mal_id');
|
||||
|
@ -180,6 +180,70 @@ class Manga extends JikanApiSearchableModel
|
||||
];
|
||||
}
|
||||
|
||||
public function getCollectionSchema(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->searchableAs(),
|
||||
'fields' => [
|
||||
[
|
||||
'name' => '.*',
|
||||
'type' => 'auto',
|
||||
],
|
||||
[
|
||||
'name' => 'title',
|
||||
'type' => 'string',
|
||||
'optional' => false,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_transformed',
|
||||
'type' => 'string',
|
||||
'optional' => false,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_japanese',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'locale' => 'jp',
|
||||
'infix' => true,
|
||||
'sort' => false
|
||||
],
|
||||
[
|
||||
'name' => 'title_japanese_transformed',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'locale' => 'jp',
|
||||
'infix' => true,
|
||||
'sort' => false
|
||||
],
|
||||
[
|
||||
'name' => 'title_english',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_english_transformed',
|
||||
'type' => 'string',
|
||||
'optional' => true,
|
||||
'infix' => true,
|
||||
'sort' => true
|
||||
],
|
||||
[
|
||||
'name' => 'title_synonyms',
|
||||
'type' => 'string[]',
|
||||
'optional' => true,
|
||||
'infix' => true,
|
||||
'sort' => false
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
public function getThemesAttribute()
|
||||
{
|
||||
|
@ -35,6 +35,14 @@ class TypeSenseScoutSearchService implements ScoutSearchService
|
||||
// in the query exhaustively, without stopping early when enough results are found.
|
||||
$options['exhaustive_search'] = env('TYPESENSE_SEARCH_EXHAUSTIVE', "true");
|
||||
$options['search_cutoff_ms'] = (int) env('TYPESENSE_SEARCH_CUTOFF_MS', 450);
|
||||
// this will be ignored together with exhaustive_search set to "true"
|
||||
$options['drop_tokens_threshold'] = (int) env('TYPESENSE_DROP_TOKENS_THRESHOLD', 1);
|
||||
$options['typo_tokens_threshold'] = (int) env('TYPESENSE_TYPO_TOKENS_THRESHOLD', 1);
|
||||
// prevent `Could not parse the filter query: unbalanced `&&` operands.` error
|
||||
// this adds support for typesense v0.24.1
|
||||
if ($options['filter_by'] === ' && ' || $options['filter_by'] === '&&') {
|
||||
unset($options['filter_by']);
|
||||
}
|
||||
|
||||
if (array_key_exists('per_page', $options) && $options['per_page'] > 250) {
|
||||
$options['per_page'] = min($this->maxItemsPerPage, 250);
|
||||
|
31
composer.lock
generated
31
composer.lock
generated
@ -11101,32 +11101,34 @@
|
||||
},
|
||||
{
|
||||
"name": "typesense/laravel-scout-typesense-driver",
|
||||
"version": "v5.1.0",
|
||||
"version": "v5.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/typesense/laravel-scout-typesense-driver.git",
|
||||
"reference": "d5b488ad8968989d9425e4b58aceb9231b569440"
|
||||
"reference": "026187e037a91c1532ecd1d209ae03c7e8733a40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/typesense/laravel-scout-typesense-driver/zipball/d5b488ad8968989d9425e4b58aceb9231b569440",
|
||||
"reference": "d5b488ad8968989d9425e4b58aceb9231b569440",
|
||||
"url": "https://api.github.com/repos/typesense/laravel-scout-typesense-driver/zipball/026187e037a91c1532ecd1d209ae03c7e8733a40",
|
||||
"reference": "026187e037a91c1532ecd1d209ae03c7e8733a40",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/bus": "^7.0|^8.0|^9.0",
|
||||
"illuminate/contracts": "^7.0|^8.0|^9.0",
|
||||
"illuminate/database": "^7.0|^8.0|^9.0",
|
||||
"illuminate/pagination": "^7.0|^8.0|^9.0",
|
||||
"illuminate/queue": "^7.0|^8.0|^9.0",
|
||||
"illuminate/support": "^7.0|^8.0|^9.0",
|
||||
"illuminate/bus": "^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/contracts": "^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/database": "^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/pagination": "^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/queue": "^7.0|^8.0|^9.0|^10.0",
|
||||
"illuminate/support": "^7.0|^8.0|^9.0|^10.0",
|
||||
"laravel/scout": "^8.0|^9.0",
|
||||
"php": "^8.0",
|
||||
"typesense/typesense-php": "^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpunit/phpunit": "^8.0|^9.0"
|
||||
"orchestra/testbench": "^6.17|^7.0|^8.0",
|
||||
"phpunit/phpunit": "^8.0|^9.0",
|
||||
"symfony/http-client": "^5.4"
|
||||
},
|
||||
"suggest": {
|
||||
"typesense/typesense-php": "Required to use the Typesense php client."
|
||||
@ -11144,7 +11146,8 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Typesense\\LaravelTypesense\\": "src/"
|
||||
"Typesense\\LaravelTypesense\\": "src/",
|
||||
"Typesense\\LaravelTypesense\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@ -11173,7 +11176,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/typesense/laravel-scout-typesense-driver/issues",
|
||||
"source": "https://github.com/typesense/laravel-scout-typesense-driver/tree/v5.1.0"
|
||||
"source": "https://github.com/typesense/laravel-scout-typesense-driver/tree/v5.2.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -11181,7 +11184,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-20T18:55:28+00:00"
|
||||
"time": "2023-05-18T07:06:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "typesense/typesense-php",
|
||||
|
Loading…
x
Reference in New Issue
Block a user