From 217e4496be34724a8960f3eb81eb0ca51fd67dec Mon Sep 17 00:00:00 2001 From: Daniel Klabbers Date: Wed, 13 Oct 2021 20:06:27 +0200 Subject: [PATCH] what i have --- extend.php | 5 ++- src/Commands/RebuildDocumentsCommand.php | 38 ++++++++++++++++ src/Mapping.php | 9 ---- src/Observe/DeletingJob.php | 28 ++++++++++++ src/Observe/Job.php | 31 ++++--------- src/Observe/Observer.php | 24 ---------- src/Observe/SavingJob.php | 42 +++++++++++++++++ src/Provider.php | 48 +++++++++++--------- src/Schemas/DiscussionSchema.php | 57 ++++++++++++++++++++++++ src/Schemas/Schema.php | 24 ++++++++++ src/Searchables/Discussion.php | 32 ------------- src/Searchables/Searchable.php | 30 ------------- 12 files changed, 227 insertions(+), 141 deletions(-) create mode 100644 src/Commands/RebuildDocumentsCommand.php delete mode 100644 src/Mapping.php create mode 100644 src/Observe/DeletingJob.php delete mode 100644 src/Observe/Observer.php create mode 100644 src/Observe/SavingJob.php create mode 100644 src/Schemas/DiscussionSchema.php create mode 100644 src/Schemas/Schema.php delete mode 100644 src/Searchables/Discussion.php delete mode 100644 src/Searchables/Searchable.php diff --git a/extend.php b/extend.php index 43d7adb..47d6a8a 100644 --- a/extend.php +++ b/extend.php @@ -11,5 +11,8 @@ return [ ->js(__DIR__ . '/js/dist/forum.js'), (new Flarum\Routes('api')) - ->get('blomstra/search', 'blomstra.search', Api\Controllers\SearchController::class) + ->get('blomstra/search', 'blomstra.search', Api\Controllers\SearchController::class), + + (new Flarum\Console) + ->command(Commands\RebuildDocumentsCommand::class) ]; diff --git a/src/Commands/RebuildDocumentsCommand.php b/src/Commands/RebuildDocumentsCommand.php new file mode 100644 index 0000000..7c215f2 --- /dev/null +++ b/src/Commands/RebuildDocumentsCommand.php @@ -0,0 +1,38 @@ +tagged('blomstra.search.schemas'); + + /** @var Queue $queue */ + $queue = $container->make(Queue::class); + + /** @var Schema $schema */ + foreach ($schemas as $schema) { + /** @var Model $model */ + $model = $schema::model(); + + $model::query()->chunk(50, function (Collection $collection) use ($model, $queue) { + $queue->push(new SavingJob($model, $collection)); + + $this->info("Pushed {$collection->count()} into the index"); + }); + } + } +} diff --git a/src/Mapping.php b/src/Mapping.php deleted file mode 100644 index b17d5f7..0000000 --- a/src/Mapping.php +++ /dev/null @@ -1,9 +0,0 @@ -getSchema(); + + if (! $schema) return; + + $keys = $this->models->map(function (Model $model) { + return $model->getKey(); + }); + + $meili->index($schema::index())->deleteDocuments( + $keys + ); + } +} diff --git a/src/Observe/Job.php b/src/Observe/Job.php index 05a3be0..4f3db44 100644 --- a/src/Observe/Job.php +++ b/src/Observe/Job.php @@ -2,33 +2,18 @@ namespace Blomstra\Search\Observe; -use Blomstra\Search\Mapping; -use Blomstra\Search\Searchables\Searchable; +use Blomstra\Search\Schemas\Schema; use Flarum\Queue\AbstractJob; -use Illuminate\Database\Eloquent\Model; -use MeiliSearch\Client; +use Illuminate\Contracts\Container\Container; -class Job extends AbstractJob +abstract class Job extends AbstractJob { - public function __construct(protected Model $model) - {} - - public function handle(Client $meili, Mapping $mapping) + protected function getSchema(): ?Schema { - $map = $mapping->get(get_class($this->model)); + $mapping = resolve(Container::class)->tagged('blomstra.search.schemas'); - /** @var Searchable $searchable */ - $searchable = new $map['searchable']($this->model); - - $body = array_merge([ - $searchable->fulltext() - ], [ - $this->model->getKeyName() => $this->model->getKey() - ]); - - $meili->index($map['index'])->addDocuments( - [$body], - $this->model->getKeyName() - ); + return collect($mapping)->first(function (Schema $schema) { + return $schema::model() === $this->class; + }); } } diff --git a/src/Observe/Observer.php b/src/Observe/Observer.php deleted file mode 100644 index a639b8f..0000000 --- a/src/Observe/Observer.php +++ /dev/null @@ -1,24 +0,0 @@ -queue()->push(new Job($model)); - } - - public function deleted($model) - { - - } - - protected function queue(): Queue - { - return resolve(Queue::class); - } -} diff --git a/src/Observe/SavingJob.php b/src/Observe/SavingJob.php new file mode 100644 index 0000000..8ae635f --- /dev/null +++ b/src/Observe/SavingJob.php @@ -0,0 +1,42 @@ +getSchema(); + + if (! $schema) return; + + if($first = $this->models->first()) { + // Set up the index + $meili->index($schema::index())->updateSettings([ + 'filterableAttributes' => array_keys($schema->filters($first)), + 'searchableAttributes' => array_keys($schema->fulltext($first)), + ]); + } + + // Preparing body for storing. + $body = $this->models->map(function (Model $model) use ($schema) { + return array_merge( + $schema->fulltext($model), + $schema->filters($model), [ + $model->getKeyName() => $model->getKey() + ]); + }); + + $meili->index($schema::index())->addDocuments( + $body->toArray(), + (new $this->class)->getKeyName() + ); + } +} diff --git a/src/Provider.php b/src/Provider.php index 8d36c6d..0798f0f 100644 --- a/src/Provider.php +++ b/src/Provider.php @@ -2,29 +2,23 @@ namespace Blomstra\Search; -use Blomstra\Search\Observe\Observer; +use Blomstra\Search\Observe\DeletingJob; +use Blomstra\Search\Observe\SavingJob; +use Blomstra\Search\Schemas\DiscussionSchema; +use Blomstra\Search\Schemas\Schema; use Flarum\Foundation\AbstractServiceProvider; -use Flarum\Post\CommentPost; use Illuminate\Contracts\Container\Container; +use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Contracts\Queue\Queue; use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use MeiliSearch\Client; class Provider extends AbstractServiceProvider { public function register() { - $this->container->singleton(Mapping::class, function () { - return new Mapping([ - \Flarum\Discussion\Discussion::class => [ - 'index' => 'discussions', - 'searchable' => \Blomstra\Search\Searchables\Discussion::class - ], - CommentPost::class => [ - 'index' => 'posts', - 'searchable' => null, - ] - ]); - }); + $this->container->tag([DiscussionSchema::class], 'blomstra.search.schemas'); $this->container->singleton(Client::class, function (Container $container) { $config = $container->make('flarum.config') ?? []; @@ -41,14 +35,24 @@ class Provider extends AbstractServiceProvider public function boot() { - /** @var Mapping $searchables */ - $searchables = $this->container->get(Mapping::class); + /** @var array $schemas */ + $schemas = $this->container->tagged('blomstra.search.schemas'); - $searchables->each(function ($mapped, $model) { - forward_static_call( - [$model, 'observe'], - Observer::class - ); - }); + /** @var Dispatcher $events */ + $events = resolve(Dispatcher::class); + + /** @var Queue $queue */ + $queue = resolve(Queue::class); + + /** @var Schema $schema */ + foreach ($schemas as $schema) { + $schema::savingOn($events, function ($model) use ($schema, $queue) { + $queue->push(new SavingJob($schema::model(), Collection::make([$model]))); + }); + + $schema::deletingOn($events, function ($model) use ($schema, $queue) { + $queue->push(new DeletingJob($schema::model(), Collection::make([$model]))); + }); + } } } diff --git a/src/Schemas/DiscussionSchema.php b/src/Schemas/DiscussionSchema.php new file mode 100644 index 0000000..256923a --- /dev/null +++ b/src/Schemas/DiscussionSchema.php @@ -0,0 +1,57 @@ +extensionEnabled('flarum-tags')) { + $filters['tags'] = $discussion->tags->pluck('id')->toArray(); + } + + return $filters; + } + + public function fulltext(Discussion $discussion): array + { + return [ + 'title' => $discussion->title, + 'content' => $discussion->firstPost?->content + ]; + } + + public static function index(): string + { + return 'discussions'; + } + + public static function model(): string + { + return Discussion::class; + } + + public static function savingOn(Dispatcher $events, callable $callable) + { + $events->listen(Started::class, function (Started $event) use ($callable) { + return $callable($event->discussion); + }); + } + + public static function deletingOn(Dispatcher $events, callable $callable) + { + $events->listen([Deleted::class, Hidden::class], function ($event) use ($callable) { + if ($event->discussion->is_private) return; + + return $callable($event->discussion); + }); + } +} diff --git a/src/Schemas/Schema.php b/src/Schemas/Schema.php new file mode 100644 index 0000000..d70a5b1 --- /dev/null +++ b/src/Schemas/Schema.php @@ -0,0 +1,24 @@ +isEnabled($extension); + } + + abstract public static function index(): string; + + abstract public static function model(): string; + + abstract public static function savingOn(Dispatcher $events, callable $callable); + abstract public static function deletingOn(Dispatcher $events, callable $callable); +} diff --git a/src/Searchables/Discussion.php b/src/Searchables/Discussion.php deleted file mode 100644 index 90b861c..0000000 --- a/src/Searchables/Discussion.php +++ /dev/null @@ -1,32 +0,0 @@ -extensionEnabled('flarum-tags')) { - return $this->discussion->tags->map(function (Tag $tag) { - return "tag:$tag->id"; - })->toArray(); - } - - return []; - } - - public function fulltext(): ?array - { - return [ - 'title' => $this->discussion->title, - 'content' => $this->discussion->firstPost->content - ]; - } -} diff --git a/src/Searchables/Searchable.php b/src/Searchables/Searchable.php deleted file mode 100644 index 49158a9..0000000 --- a/src/Searchables/Searchable.php +++ /dev/null @@ -1,30 +0,0 @@ -isEnabled($extension); - } -}