Skip to content

Commit

Permalink
feat: Improving the theme search by boosting song name (#734)
Browse files Browse the repository at this point in the history
  • Loading branch information
Maniload authored Aug 27, 2024
1 parent db0fbe9 commit 7458653
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 248 deletions.
82 changes: 82 additions & 0 deletions app/Scout/Elasticsearch/Api/Query/ElasticQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,86 @@ abstract class ElasticQuery
* @return SearchParametersBuilder
*/
abstract public function build(Criteria $criteria): SearchParametersBuilder;

/**
* Helper function for raw queries. This will create four queries against a text field:
* - Matching the exact phrase (x1.0)
* - Matching all terms (words) (x1.0)
* - Matching at least one term (word) (x0.6)
* - Matching fuzzy (x0.4)
*
* @param string $field
* @param string $searchTerm
* @return array
*/
protected function createTextQuery(string $field, string $searchTerm): array
{
return [
[
'match_phrase' => [
$field => [
'query' => $searchTerm,
],
],
],
[
'match' => [
$field => [
'query' => $searchTerm,
'operator' => 'AND',
],
],
],
[
'match' => [
$field => [
'query' => $searchTerm,
'boost' => 0.6,
],
],
],
[
'fuzzy' => [
$field => [
'value' => $searchTerm,
'boost' => 0.4,
],
],
],
];
}

/**
* Helper function for raw queries. This will wrap queries in nested queries.
*
* @param string $nestedResource
* @param array $nestedQueries
* @return array
*/
protected function createNestedQuery(string $nestedResource, array $nestedQueries): array
{
return array_map(
fn(array $nestedQuery) => [
'nested' => [
'path' => $nestedResource,
'query' => $nestedQuery,
],
],
$nestedQueries
);
}

/**
* Shorthand function for calling `$this->createNestedQuery()` with the output from
* `$this->createTextQuery()`.
*
* @param string $nestedResource
* @param string $field
* @param string $searchTerm
* @return array
*/
protected function createNestedTextQuery(string $nestedResource, string $field, string $searchTerm): array
{
return $this->createNestedQuery($nestedResource, $this->createTextQuery("$nestedResource.$field", $searchTerm));
}
}
206 changes: 40 additions & 166 deletions app/Scout/Elasticsearch/Api/Query/Wiki/Anime/ThemeQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
use App\Http\Api\Criteria\Search\Criteria;
use App\Models\Wiki\Anime\AnimeTheme;
use App\Scout\Elasticsearch\Api\Query\ElasticQuery;
use Elastic\ScoutDriverPlus\Builders\MatchPhraseQueryBuilder;
use Elastic\ScoutDriverPlus\Builders\MatchQueryBuilder;
use Elastic\ScoutDriverPlus\Builders\NestedQueryBuilder;
use Elastic\ScoutDriverPlus\Builders\SearchParametersBuilder;
use Elastic\ScoutDriverPlus\Support\Query;

Expand All @@ -27,169 +24,46 @@ class ThemeQuery extends ElasticQuery
public function build(Criteria $criteria): SearchParametersBuilder
{
$query = Query::bool()
->should(
(new MatchPhraseQueryBuilder())
->field('slug')
->query($criteria->getTerm())
)
->should(
(new MatchQueryBuilder())
->field('slug')
->query($criteria->getTerm())
->operator('AND')
)
->should(
(new MatchQueryBuilder())
->field('slug')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
->should(
(new MatchPhraseQueryBuilder())
->field('anime_slug')
->query($criteria->getTerm())
)
->should(
(new MatchQueryBuilder())
->field('anime_slug')
->query($criteria->getTerm())
->operator('AND')
)
->should(
(new MatchQueryBuilder())
->field('anime_slug')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
->should(
(new MatchPhraseQueryBuilder())
->field('synonym_slug')
->query($criteria->getTerm())
)
->should(
(new MatchQueryBuilder())
->field('synonym_slug')
->query($criteria->getTerm())
->operator('AND')
)
->should(
(new MatchQueryBuilder())
->field('synonym_slug')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
->should(
(new NestedQueryBuilder())
->path('anime')
->query(
(new MatchPhraseQueryBuilder())
->field('anime.name')
->query($criteria->getTerm())
)
)
->should(
(new NestedQueryBuilder())
->path('anime')
->query(
(new MatchQueryBuilder())
->field('anime.name')
->query($criteria->getTerm())
->operator('AND')
)
)
->should(
(new NestedQueryBuilder())
->path('anime')
->query(
(new MatchQueryBuilder())
->field('anime.name')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
)
->should(
(new NestedQueryBuilder())
->path('anime')
->query(
(new NestedQueryBuilder())
->path('anime.synonyms')
->query(
(new MatchPhraseQueryBuilder())
->field('anime.synonyms.text')
->query($criteria->getTerm())
)
)
)
->should(
(new NestedQueryBuilder())
->path('anime')
->query(
(new NestedQueryBuilder())
->path('anime.synonyms')
->query(
(new MatchQueryBuilder())
->field('anime.synonyms.text')
->query($criteria->getTerm())
->operator('AND')
)
)
)
->should(
(new NestedQueryBuilder())
->path('anime')
->query(
(new NestedQueryBuilder())
->path('anime.synonyms')
->query(
(new MatchQueryBuilder())
->field('anime.synonyms.text')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
)
)
->should(
(new NestedQueryBuilder())
->path('song')
->query(
(new MatchPhraseQueryBuilder())
->field('song.title')
->query($criteria->getTerm())
)
)
->should(
(new NestedQueryBuilder())
->path('song')
->query(
(new MatchQueryBuilder())
->field('song.title')
->query($criteria->getTerm())
->operator('AND')
)
)
->should(
(new NestedQueryBuilder())
->path('song')
->query(
(new MatchQueryBuilder())
->field('song.title')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
)
->minimumShouldMatch(1);
->mustRaw([
// The more sub-queries match the better the score will be.
'bool' => [
'should' => [
[
// Pick the score of the best performing sub-query.
'dis_max' => [
'queries' => [
[
'bool' => [
'should' => $this->createNestedTextQuery('song', 'title', $criteria->getTerm()),
],
],
[
'bool' => [
'boost' => 0.5,
'should' => $this->createNestedTextQuery('anime', 'name', $criteria->getTerm()),
],
],
[
'bool' => [
'boost' => 0.5 * 0.85,
'should' => $this->createNestedQuery(
'anime',
$this->createNestedTextQuery('anime.synonyms', 'text', $criteria->getTerm()),
),
],
],
],
],
],
[
'bool' => [
'boost' => 0.75,
'should' => $this->createTextQuery('slug', $criteria->getTerm()),
],
]
],
],
]);

return AnimeTheme::searchQuery($query);
}
Expand Down
Loading

0 comments on commit 7458653

Please sign in to comment.