From 29ba86484999bb336dad8b3b74f1ff09e88f9e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20Klabbers?= Date: Wed, 9 Nov 2022 18:06:48 +0100 Subject: [PATCH] settings configurations --- js/src/admin/index.ts | 25 +++++++ src/Api/Controllers/SearchController.php | 93 ++++++++++-------------- src/Provider.php | 6 ++ src/Searchers/CommentPostSearcher.php | 17 +++++ src/Searchers/DiscussionSearcher.php | 22 ++++++ src/Searchers/Searcher.php | 36 +++++++++ 6 files changed, 145 insertions(+), 54 deletions(-) create mode 100644 src/Searchers/CommentPostSearcher.php create mode 100644 src/Searchers/DiscussionSearcher.php create mode 100644 src/Searchers/Searcher.php diff --git a/js/src/admin/index.ts b/js/src/admin/index.ts index ce06dab..2cb3bd7 100644 --- a/js/src/admin/index.ts +++ b/js/src/admin/index.ts @@ -78,5 +78,30 @@ app.initializers.add('blomstra-search', () => { label: app.translator.trans('blomstra-search.admin.elastic-index'), default: 'flarum', type: 'input', + }) + .registerSetting({ + setting: 'blomstra-search.search-discussion-subjects', + label: app.translator.trans('blomstra-search.admin.search-discussion-subjects'), + type: 'switch', + }) + .registerSetting({ + setting: 'blomstra-search.search-post-bodies', + label: app.translator.trans('blomstra-search.admin.search-post-bodies'), + type: 'switch', + }) + .registerSetting({ + setting: 'blomstra-search.match-sentences', + label: app.translator.trans('blomstra-search.admin.match-sentences'), + type: 'switch', + }) + .registerSetting({ + setting: 'blomstra-search.match-words', + label: app.translator.trans('blomstra-search.admin.match-words'), + type: 'switch', + }) + .registerSetting({ + setting: 'blomstra-search.match-fragments', + label: app.translator.trans('blomstra-search.admin.match-fragments'), + type: 'switch', }); }); diff --git a/src/Api/Controllers/SearchController.php b/src/Api/Controllers/SearchController.php index 644e66d..2ab4e1b 100644 --- a/src/Api/Controllers/SearchController.php +++ b/src/Api/Controllers/SearchController.php @@ -6,6 +6,7 @@ use Blomstra\Search\Elasticsearch\MatchPhraseQuery; use Blomstra\Search\Elasticsearch\MatchQuery; use Blomstra\Search\Save\Document as ElasticDocument; use Blomstra\Search\Elasticsearch\TermsQuery; +use Blomstra\Search\Searchers\Searcher; use Elasticsearch\Client; use Flarum\Api\Controller\ListDiscussionsController; use Flarum\Api\Serializer\DiscussionSerializer; @@ -14,6 +15,7 @@ use Flarum\Extension\ExtensionManager; use Flarum\Group\Group; use Flarum\Http\RequestUtil; use Flarum\Http\UrlGenerator; +use Flarum\Settings\SettingsRepositoryInterface; use Flarum\User\User; use Illuminate\Contracts\Container\Container; use Illuminate\Support\Arr; @@ -37,8 +39,19 @@ class SearchController extends ListDiscussionsController 'commentCount' => 'comment_count' ]; - public function __construct(protected Client $elastic, protected UrlGenerator $uri) - {} + protected iterable $searchers; + protected bool $matchSentences; + protected bool $matchWords; + protected bool $matchFragments; + + public function __construct(protected Client $elastic, protected UrlGenerator $uri, Container $container, SettingsRepositoryInterface $settings) + { + $this->searchers = $container->tagged('blomstra.search.searchers'); + + $this->matchSentences = (bool) $settings->get('blomstra-search.match-sentences', true); + $this->matchWords = (bool) $settings->get('blomstra-search.match-words', true); + $this->matchFragments = (bool) $settings->get('blomstra-search.match-fragments', true); + } protected function data(ServerRequestInterface $request, Document $document) { @@ -59,13 +72,10 @@ class SearchController extends ListDiscussionsController $filterQuery = BoolQuery::create(); if (! empty($search)) { - $filterQuery - // @todo commented out to use only partial matching for now - ->add($this->sentenceMatch($search)) - ->add($this->wordMatch($search, 'and')) - ->add($this->wordMatch($search, 'or')) -// ->add($this->partialMatch($search)) - ; + if ($this->matchSentences) $filterQuery->add($this->sentenceMatch($search)); + if ($this->matchWords) $filterQuery->add($this->wordMatch($search, 'and')); + if ($this->matchWords) $filterQuery->add($this->wordMatch($search, 'or')); + if ($this->matchFragments) $filterQuery->add($this->partialMatch($search)); } $builder = (new Builder($this->elastic)) @@ -221,25 +231,28 @@ class SearchController extends ListDiscussionsController return $query; } + protected function boolQuery(Query $parent, float $boost = 1) + { + /** @var Searcher $searcher */ + foreach ($this->searchers as $searcher) { + $searcher = new $searcher; + + $parent->add( + BoolQuery::create() + ->add(TermQuery::create('type', $searcher->type()), 'filter') + ->add($parent->boost($boost * $searcher->boost())), + 'should' + ); + } + + return $parent; + } + protected function sentenceMatch(string $q): Query { $query = (new MatchPhraseQuery('content', $q)); - return BoolQuery::create() - // Discussion titles - ->add( - BoolQuery::create() - ->add(TermQuery::create('type', 'discussions'), 'filter') - ->add($query->boost(2)), - 'should' - ) - // Post bodies - ->add( - BoolQuery::create() - ->add(TermQuery::create('type', 'posts'), 'filter') - ->add($query->boost(1.9)), - 'should' - ); + return $this->boolQuery($query, 2); } protected function wordMatch(string $q, string $operator = 'or') @@ -249,42 +262,14 @@ class SearchController extends ListDiscussionsController $boost = $operator === 'and' ? 1 : .8; - return BoolQuery::create() - // Discussion titles - ->add( - BoolQuery::create() - ->add(TermQuery::create('type', 'discussions'), 'filter') - ->add($query->boost($boost * 1.8)), - 'should' - ) - // Post bodies - ->add( - BoolQuery::create() - ->add(TermQuery::create('type', 'posts'), 'filter') - ->add($query->boost($boost * 1.8)), - 'should' - ); + return $this->boolQuery($query, $boost); } protected function partialMatch(string $q) { $query = (new MatchQuery('content', $q)); - return BoolQuery::create() - // Discussion titles - ->add( - BoolQuery::create() - ->add(TermQuery::create('type', 'discussions'), 'filter') - ->add(clone $query->boost(1.6)), - 'should' - ) - // Post bodies - ->add( - BoolQuery::create() - ->add(TermQuery::create('type', 'posts'), 'filter') - ->add(clone $query->boost(1.3)), - 'should' - ); + return $this->boolQuery($query, .6); } diff --git a/src/Provider.php b/src/Provider.php index 4bd7994..479eb5e 100644 --- a/src/Provider.php +++ b/src/Provider.php @@ -5,6 +5,7 @@ namespace Blomstra\Search; use Blomstra\Search\Jobs\DeletingJob; use Blomstra\Search\Jobs\Job; use Blomstra\Search\Jobs\SavingJob; +use Blomstra\Search\Searchers; use Blomstra\Search\Seeders; use Elasticsearch\Client as Elastic; use Elasticsearch\ClientBuilder; @@ -79,6 +80,11 @@ class Provider extends AbstractServiceProvider return new Api\Client($pipe); } ); + + $this->container->tag([ + Searchers\DiscussionSearcher::class, + Searchers\CommentPostSearcher::class, + ], 'blomstra.search.searchers'); } public function boot() diff --git a/src/Searchers/CommentPostSearcher.php b/src/Searchers/CommentPostSearcher.php new file mode 100644 index 0000000..cd52a5c --- /dev/null +++ b/src/Searchers/CommentPostSearcher.php @@ -0,0 +1,17 @@ +setting('blomstra-search.admin.search-post-bodies', true); + + return boolval($enabled); + } +} diff --git a/src/Searchers/DiscussionSearcher.php b/src/Searchers/DiscussionSearcher.php new file mode 100644 index 0000000..3f218d9 --- /dev/null +++ b/src/Searchers/DiscussionSearcher.php @@ -0,0 +1,22 @@ +setting('blomstra-search.search-discussion-subjects', true); + + return boolval($enabled); + } + + public function boost(): float + { + return 1.5; + } +} diff --git a/src/Searchers/Searcher.php b/src/Searchers/Searcher.php new file mode 100644 index 0000000..400d37f --- /dev/null +++ b/src/Searchers/Searcher.php @@ -0,0 +1,36 @@ +seeder; + + if (empty($seeder)) throw new \InvalidArgumentException("Implement type or add \$seeder"); + + return (new $seeder)->type(); + } + + public function enabled(): bool + { + return true; + } + + public function boost(): float + { + return 1; + } + + protected function setting(string $key, $default = null) + { + return resolve(SettingsRepositoryInterface::class)->get($key, $default); + } +}