From 57748793311f526edfe3100ac6f40ea79419e8fa Mon Sep 17 00:00:00 2001 From: JM Date: Wed, 22 Apr 2026 20:19:09 +0200 Subject: [PATCH] fuzzy search in thread --- src/Api/Controllers/SearchController.php | 7 +- src/Commands/BuildCommand.php | 87 ++++++++++++++---------- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/Api/Controllers/SearchController.php b/src/Api/Controllers/SearchController.php index 661ad74..6c5f82c 100644 --- a/src/Api/Controllers/SearchController.php +++ b/src/Api/Controllers/SearchController.php @@ -375,9 +375,10 @@ class SearchController extends ListDiscussionsController if ($this->matchSentences) { $should->add((new MatchPhraseQuery('content', $search))->boost(2 * $boost), 'should'); } - if ($this->matchWords) { - $should->add((new MatchQuery('content', $search))->operator('and')->boost(1.8 * $boost), 'should'); - } + if ($this->matchWords) { + $should->add((new MatchQuery('content', $search))->operator('and')->boost(1.8 * $boost), 'should'); + $should->add((new MatchQuery('content.autocomplete', $search))->operator('and')->boost(0.30 * $boost), 'should'); + } return $should; } diff --git a/src/Commands/BuildCommand.php b/src/Commands/BuildCommand.php index edc7bb0..7181a4f 100644 --- a/src/Commands/BuildCommand.php +++ b/src/Commands/BuildCommand.php @@ -561,49 +561,62 @@ HELP; ]; } - protected function mappingProperties(): array - { - $language = resolve(SettingsRepositoryInterface::class)->get('blomstra-search.analyzer-language') ?: 'english'; +protected function mappingProperties(): array +{ + $language = resolve(SettingsRepositoryInterface::class)->get('blomstra-search.analyzer-language') ?: 'english'; - $titleMapping = [ - 'type' => 'text', - 'analyzer' => 'flarum_analyzer', - ]; + $titleMapping = [ + 'type' => 'text', + 'analyzer' => 'flarum_analyzer', + ]; - // Only add the autocomplete subfield for non-CJK languages. - if ($language !== 'cjk') { - $titleMapping['fields'] = [ - 'autocomplete' => [ - 'type' => 'text', - 'analyzer' => 'flarum_title_autocomplete', - 'search_analyzer' => 'flarum_title_search', - ], - ]; - } - - return [ - '_meta' => ['index_compat_version' => self::INDEX_COMPAT_VERSION], - 'properties' => [ - 'join_field' => ['type' => 'join', 'relations' => ['discussion' => 'post']], - 'discussion_id' => ['type' => 'integer'], - 'content' => ['type' => 'text', 'analyzer' => 'flarum_analyzer'], - 'title' => $titleMapping, - 'rawId' => ['type' => 'integer'], - 'created_at' => ['type' => 'date'], - 'updated_at' => ['type' => 'date'], - 'is_private' => ['type' => 'boolean'], - 'is_sticky' => ['type' => 'boolean'], - 'groups' => ['type' => 'integer'], - 'tags' => ['type' => 'integer'], - 'recipient_groups' => ['type' => 'integer'], - 'recipient_users' => ['type' => 'integer'], - 'comment_count' => ['type' => 'integer'], - 'view_count' => ['type' => 'integer'], - 'is_hidden' => ['type' => 'boolean'], + // Only add the autocomplete subfield for non-CJK languages. + if ($language !== 'cjk') { + $titleMapping['fields'] = [ + 'autocomplete' => [ + 'type' => 'text', + 'analyzer' => 'flarum_title_autocomplete', + 'search_analyzer' => 'flarum_title_search', ], ]; } + $contentMapping = [ + 'type' => 'text', + 'analyzer' => 'flarum_analyzer', + ]; + + // Only add the autocomplete subfield for non-CJK languages. + if ($language !== 'cjk') { + $contentMapping['fields'] = [ + 'autocomplete' => [ + 'type' => 'text', + 'analyzer' => 'flarum_title_autocomplete', + 'search_analyzer' => 'flarum_title_search', + ], + ]; + } + + return [ + '_meta' => ['index_compat_version' => self::INDEX_COMPAT_VERSION], + 'properties' => [ + 'join_field' => ['type' => 'join', 'relations' => ['discussion' => 'post']], + 'discussion_id' => ['type' => 'integer'], + 'content' => $contentMapping, + 'title' => $titleMapping, + 'rawId' => ['type' => 'integer'], + 'created_at' => ['type' => 'date'], + 'updated_at' => ['type' => 'date'], + 'is_private' => ['type' => 'boolean'], + 'user_id' => ['type' => 'integer'], + 'groups' => ['type' => 'keyword'], + 'comment_count' => ['type' => 'integer'], + 'tags' => ['type' => 'keyword'], + 'is_sticky' => ['type' => 'boolean'], + 'is_hidden' => ['type' => 'boolean'], + ], + ]; +} /** * Query ES for rawIds already indexed in $targetIndex for the given $joinRelation and ID range. * Retries on transient ES failures (NoNodesAvailableException / other ElasticsearchException)