moved to elastic
This commit is contained in:
parent
e2e56831e5
commit
f69541d38a
|
|
@ -21,10 +21,8 @@
|
|||
],
|
||||
"require": {
|
||||
"php": ">= 8.0",
|
||||
"flarum/core": "^1.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"meilisearch/meilisearch-php": "Required to use the MeiliSearch engine (^0.19)."
|
||||
"flarum/core": "^1.0.0",
|
||||
"elasticsearch/elasticsearch": "7.*"
|
||||
},
|
||||
"extra": {
|
||||
"flarum-extension": {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -64,7 +64,7 @@ export default class DiscussionsSearchSource implements SearchSource {
|
|||
|
||||
return (
|
||||
<>
|
||||
<li className="Dropdown-header">{app.translator.trans('core.forum.search.discussions_heading')}</li>,
|
||||
<li className="Dropdown-header">{app.translator.trans('core.forum.search.discussions_heading')}</li>
|
||||
<li>
|
||||
<LinkButton icon="fas fa-search" href={app.route('index', { q: query })}>
|
||||
{app.translator.trans('core.forum.search.all_discussions_button', { query })}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Blomstra\Search\Api\Controllers;
|
||||
|
||||
use Blomstra\Search\Schemas\Schema;
|
||||
use Elasticsearch\Client;
|
||||
use Flarum\Api\Controller\AbstractListController;
|
||||
use Flarum\Extension\ExtensionManager;
|
||||
use Flarum\Group\Group;
|
||||
|
|
@ -11,17 +12,16 @@ use Flarum\User\User;
|
|||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use MeiliSearch\Client;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Tobscure\JsonApi\Document;
|
||||
|
||||
class SearchController extends AbstractListController
|
||||
{
|
||||
public function __construct(protected Client $meili)
|
||||
{}
|
||||
|
||||
protected function data(ServerRequestInterface $request, Document $document)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = resolve('blomstra.search.elastic');
|
||||
|
||||
$index = Arr::get($request->getQueryParams(), 'index');
|
||||
|
||||
$actor = RequestUtil::getActor($request);
|
||||
|
|
@ -30,20 +30,26 @@ class SearchController extends AbstractListController
|
|||
|
||||
$schema = $this->getSchema($index);
|
||||
|
||||
$result = $this->meili->index($index)->search($filters['q'], [
|
||||
'offset' => $this->extractOffset($request),
|
||||
'limit' => $this->extractLimit($request),
|
||||
$result = $client->search([
|
||||
'index' => $index,
|
||||
'from' => $this->extractOffset($request),
|
||||
'size' => $this->extractLimit($request),
|
||||
'sort' => $this->extractSort($request),
|
||||
// Filters based on permissions etc..
|
||||
'filter' => $this->getFilters($actor)
|
||||
'body' => [
|
||||
'query' => [
|
||||
'multi_match' => [
|
||||
'query' => $filters['q'],
|
||||
'fields' => array_keys($schema->fulltext(new ($schema::model())))
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->serializer = $schema::serializer();
|
||||
|
||||
return Collection::make($result->getHits())
|
||||
->map(function ($hit) use ($schema) {
|
||||
return $schema::model()::query()->find($hit['id']);
|
||||
});
|
||||
$ids = Collection::make(Arr::get($result, 'hits.hits'))->pluck('_id')->toArray();
|
||||
|
||||
return $schema::model()::query()->findMany($ids);
|
||||
}
|
||||
|
||||
protected function getSchema(string $index): ?Schema
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ namespace Blomstra\Search\Commands;
|
|||
|
||||
use Blomstra\Search\Observe\SavingJob;
|
||||
use Blomstra\Search\Schemas\Schema;
|
||||
use Elasticsearch\Client;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Queue\Queue;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use MeiliSearch\Client;
|
||||
|
||||
class RebuildDocumentsCommand extends Command
|
||||
{
|
||||
|
|
@ -24,8 +24,8 @@ class RebuildDocumentsCommand extends Command
|
|||
/** @var Queue $queue */
|
||||
$queue = $container->make(Queue::class);
|
||||
|
||||
/** @var Client $meili */
|
||||
$meili = $container->make(Client::class);
|
||||
/** @var Client $client */
|
||||
$client = $container->make('blomstra.search.elastic');
|
||||
|
||||
/** @var Schema $schema */
|
||||
foreach ($schemas as $schema) {
|
||||
|
|
@ -33,13 +33,21 @@ class RebuildDocumentsCommand extends Command
|
|||
$model = $schema::model();
|
||||
|
||||
// Flush the index.
|
||||
if ($this->option('flush')) $meili->index($schema::index())->delete();
|
||||
if ($this->option('flush')) $client->indices()->delete([
|
||||
'index' => $schema::index()
|
||||
]);
|
||||
|
||||
$model::query()->chunk(50, function (Collection $collection) use ($model, $queue) {
|
||||
$total = 0;
|
||||
|
||||
$model::query()->chunk(50, function (Collection $collection) use ($model, $queue, &$total) {
|
||||
$queue->push(new SavingJob($model, $collection));
|
||||
|
||||
$this->info("Pushed {$collection->count()} into the index");
|
||||
$this->info("Pushed {$collection->count()} into the index.");
|
||||
|
||||
$total += $collection->count();
|
||||
});
|
||||
|
||||
$this->info("Pushed a total of $total into the index.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,41 +2,70 @@
|
|||
|
||||
namespace Blomstra\Search\Observe;
|
||||
|
||||
use Elasticsearch\Client;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use MeiliSearch\Client;
|
||||
|
||||
class SavingJob extends Job
|
||||
{
|
||||
public function __construct(protected string $class, protected Collection $models)
|
||||
{}
|
||||
|
||||
public function handle(Client $meili)
|
||||
public function handle(Container $container)
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $container->make('blomstra.search.elastic');
|
||||
|
||||
$schema = $this->getSchema();
|
||||
|
||||
if (! $schema) return;
|
||||
|
||||
if($first = $this->models->first()) {
|
||||
$properties = [];
|
||||
|
||||
foreach (array_keys($schema->fulltext($first)) as $key) {
|
||||
$properties[$key] = ['type' => 'text'];
|
||||
}
|
||||
|
||||
// Set up the index
|
||||
$meili->index($schema::index())->updateSettings([
|
||||
'filterableAttributes' => array_keys($schema->filters($first)),
|
||||
'searchableAttributes' => array_keys($schema->fulltext($first)),
|
||||
]);
|
||||
// if (! $client->indices()->exists([
|
||||
// 'index' => $schema::index(),
|
||||
// 'expand_wildcards' => 'none'
|
||||
// ])) {
|
||||
// $client->indices()->create([
|
||||
// 'index' => $schema::index(),
|
||||
// 'body' => [
|
||||
// 'mappings' => [
|
||||
// 'properties' => $properties
|
||||
// ],
|
||||
// 'settings' => [
|
||||
// 'index' => [
|
||||
// 'query' => [
|
||||
// 'default_field' => array_keys($schema->fulltext($first))
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// ]
|
||||
// ]);
|
||||
// }
|
||||
}
|
||||
|
||||
// Preparing body for storing.
|
||||
$body = $this->models->map(function (Model $model) use ($schema) {
|
||||
return array_merge(
|
||||
return [
|
||||
['index' => ['_id' => $model->getKey(), '_index' => $schema::index()]],
|
||||
array_merge(
|
||||
$schema->fulltext($model),
|
||||
$schema->filters($model), [
|
||||
$model->getKeyName() => $model->getKey()
|
||||
]);
|
||||
});
|
||||
$schema->filters($model))
|
||||
|
||||
$meili->index($schema::index())->addDocuments(
|
||||
$body->toArray(),
|
||||
(new $this->class)->getKeyName()
|
||||
);
|
||||
];
|
||||
})->flatten(1);
|
||||
|
||||
$response = $client->bulk([
|
||||
'index' => $schema::index(),
|
||||
'body' => $body->toArray(),
|
||||
'refresh' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ use Blomstra\Search\Observe\DeletingJob;
|
|||
use Blomstra\Search\Observe\SavingJob;
|
||||
use Blomstra\Search\Schemas\DiscussionSchema;
|
||||
use Blomstra\Search\Schemas\Schema;
|
||||
use Elasticsearch\ClientBuilder;
|
||||
use Flarum\Foundation\AbstractServiceProvider;
|
||||
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;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Provider extends AbstractServiceProvider
|
||||
{
|
||||
|
|
@ -20,16 +21,16 @@ class Provider extends AbstractServiceProvider
|
|||
{
|
||||
$this->container->tag([DiscussionSchema::class], 'blomstra.search.schemas');
|
||||
|
||||
$this->container->singleton(Client::class, function (Container $container) {
|
||||
$this->container->singleton('blomstra.search.elastic', function (Container $container) {
|
||||
$config = $container->make('flarum.config') ?? [];
|
||||
|
||||
$meili = Arr::get($config, 'meili');
|
||||
$elastic = Arr::get($config, 'elastic');
|
||||
|
||||
if (! $meili) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Client($meili);
|
||||
return ClientBuilder::create()
|
||||
->setHosts([$elastic['endpoint']])
|
||||
->setBasicAuthentication($elastic['username'], $elastic['password'])
|
||||
->setLogger($container->make(LoggerInterface::class))
|
||||
->build();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,10 +44,13 @@ class DiscussionSchema extends Schema
|
|||
})->flatten();
|
||||
}
|
||||
|
||||
if (! $permissions || $permissions->isEmpty()) {
|
||||
if (! $discussion->is_private && (! $permissions || $permissions->isEmpty())) {
|
||||
$permissions = Permission::query()
|
||||
->where('permission', 'viewForum')
|
||||
->pluck('group_id');
|
||||
|
||||
} else {
|
||||
$permissions = collect();
|
||||
}
|
||||
|
||||
$filters['groups'] = $permissions->toArray();
|
||||
|
|
|
|||
Loading…
Reference in New Issue