Merge branch 'dk/analyzer' into main
This commit is contained in:
commit
ef4b02b562
|
|
@ -9,6 +9,10 @@ return [
|
||||||
|
|
||||||
(new Flarum\Frontend('forum'))
|
(new Flarum\Frontend('forum'))
|
||||||
->js(__DIR__ . '/js/dist/forum.js'),
|
->js(__DIR__ . '/js/dist/forum.js'),
|
||||||
|
(new Flarum\Frontend('admin'))
|
||||||
|
->js(__DIR__ . '/js/dist/admin.js'),
|
||||||
|
|
||||||
|
(new Flarum\Locales(__DIR__ . '/resources/locale')),
|
||||||
|
|
||||||
(new Flarum\Routes('api'))
|
(new Flarum\Routes('api'))
|
||||||
->get('/blomstra/search/{type}', 'blomstra.search', Api\Controllers\SearchController::class),
|
->get('/blomstra/search/{type}', 'blomstra.search', Api\Controllers\SearchController::class),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './src/admin';
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -14,7 +14,7 @@
|
||||||
"flarum-webpack-config": "^1.0.0",
|
"flarum-webpack-config": "^1.0.0",
|
||||||
"pusher-js": "^7.0.3",
|
"pusher-js": "^7.0.3",
|
||||||
"webpack": "^4.46.0",
|
"webpack": "^4.46.0",
|
||||||
"webpack-cli": "^4.9.0"
|
"webpack-cli": "^4.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.4.1"
|
"prettier": "^2.4.1"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import app from 'flarum/admin/app';
|
||||||
|
|
||||||
|
app.initializers.add('blomstra-search', () => {
|
||||||
|
const languages = new Map;
|
||||||
|
['arabic', 'armenian', 'basque', 'bengali', 'brazilian', 'bulgarian', 'catalan', 'cjk', 'czech',
|
||||||
|
'danish', 'dutch', 'english', 'estonian', 'finnish', 'french', 'galician', 'german', 'greek',
|
||||||
|
'hindi', 'hungarian', 'indonesian', 'irish', 'italian', 'latvian', 'lithuanian', 'norwegian',
|
||||||
|
'persian', 'portuguese', 'romanian', 'russian', 'sorani', 'spanish', 'swedish', 'turkish', 'thai']
|
||||||
|
.forEach(language => {
|
||||||
|
languages.set(language, language);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.extensionData
|
||||||
|
.for('blomstra-search')
|
||||||
|
.registerSetting({
|
||||||
|
setting: 'blomstra-search.elastic-endpoint',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.elastic-endpoint'),
|
||||||
|
type: 'input'
|
||||||
|
})
|
||||||
|
.registerSetting({
|
||||||
|
setting: 'blomstra-search.elastic-username',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.elastic-username'),
|
||||||
|
type: 'input'
|
||||||
|
})
|
||||||
|
.registerSetting({
|
||||||
|
setting: 'blomstra-search.elastic-password',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.elastic-password'),
|
||||||
|
type: 'password'
|
||||||
|
})
|
||||||
|
.registerSetting({
|
||||||
|
setting: 'blomstra-search.elastic-index',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.elastic-index'),
|
||||||
|
default: 'flarum',
|
||||||
|
type: 'input'
|
||||||
|
})
|
||||||
|
.registerSetting({
|
||||||
|
setting: 'blomstra-search.analyzer-language',
|
||||||
|
label: app.translator.trans('blomstra-search.admin.analyzer.label'),
|
||||||
|
help: app.translator.trans('blomstra-search.admin.analyzer.help'),
|
||||||
|
type: 'select',
|
||||||
|
options: Object.fromEntries(languages.entries()),
|
||||||
|
default: 'english',
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
blomstra-search:
|
||||||
|
admin:
|
||||||
|
elastic-endpoint: Elastic Endpoint
|
||||||
|
elastic-username: => core.ref.username
|
||||||
|
elastic-password: => core.ref.password
|
||||||
|
elastic-index: Index
|
||||||
|
analyzer:
|
||||||
|
label: Analyzer language
|
||||||
|
help: |
|
||||||
|
The analyzer makes search understand stop words and undertakes language
|
||||||
|
specific improvements for indexing.
|
||||||
|
|
@ -90,35 +90,45 @@ class SearchController extends ListDiscussionsController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we need to retrieve all discussion ids and when the results are posts,
|
||||||
|
// their ids as most relevant post id
|
||||||
$results = Collection::make(Arr::get($result, 'hits.hits'))
|
$results = Collection::make(Arr::get($result, 'hits.hits'))
|
||||||
->map(function ($hit) {
|
->map(function ($hit) {
|
||||||
$id = Str::after($hit['_source']['id'], ':');
|
$id = Str::after($hit['_source']['id'], ':');
|
||||||
$type = $hit['_source']['type'];
|
$type = $hit['_source']['type'];
|
||||||
|
|
||||||
if ($type === 'posts') {
|
if ($type === 'posts') {
|
||||||
/** @var Discussion $discussion */
|
return [
|
||||||
$discussion = Discussion::whereHas('posts', function ($query) use ($id) {
|
'most_relevant_post_id' => $id,
|
||||||
$query->where('id', $id);
|
];
|
||||||
})->first();
|
} else {
|
||||||
|
return [
|
||||||
$discussion->most_relevant_post_id = $id;
|
'discussion_id' => $id
|
||||||
|
];
|
||||||
}
|
}
|
||||||
if ($type === 'discussions') {
|
});
|
||||||
/** @var Discussion $discussion */
|
|
||||||
$discussion = Discussion::find($id);
|
|
||||||
|
|
||||||
|
$discussions = Discussion::query()
|
||||||
|
->whereIn('id', $results->pluck('discussion_id'))
|
||||||
|
->orWhereHas('posts', function ($query) use ($results) {
|
||||||
|
$query->whereIn('id', $results->pluck('most_relevant_post_id'));
|
||||||
|
})
|
||||||
|
->get()
|
||||||
|
->map(function (Discussion $discussion) use ($results) {
|
||||||
|
if (in_array($discussion->id, $results->pluck('discussion_id'))) {
|
||||||
$discussion->most_relevant_post_id = $discussion->first_post_id;
|
$discussion->most_relevant_post_id = $discussion->first_post_id;
|
||||||
|
} else {
|
||||||
|
$post = $discussion->posts()->whereIn('id', $results->pluck('most_relevant_post_id'))->first();
|
||||||
|
$discussion->most_relevant_post_id = $post?->id ?? $discussion->first_post_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $discussion;
|
|
||||||
})
|
})
|
||||||
->keyBy('id')
|
->keyBy('id')
|
||||||
->unique();
|
->unique();
|
||||||
|
|
||||||
$this->loadRelations($results, $include);
|
$this->loadRelations($discussions, $include);
|
||||||
|
|
||||||
if ($relations = array_intersect($include, ['firstPost', 'lastPost', 'mostRelevantPost'])) {
|
if ($relations = array_intersect($include, ['firstPost', 'lastPost', 'mostRelevantPost'])) {
|
||||||
foreach ($results as $discussion) {
|
foreach ($discussions as $discussion) {
|
||||||
foreach ($relations as $relation) {
|
foreach ($relations as $relation) {
|
||||||
if ($discussion->$relation) {
|
if ($discussion->$relation) {
|
||||||
$discussion->$relation->discussion = $discussion;
|
$discussion->$relation->discussion = $discussion;
|
||||||
|
|
@ -127,7 +137,7 @@ class SearchController extends ListDiscussionsController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $discussions;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDocument(string $type): ?ElasticDocument
|
protected function getDocument(string $type): ?ElasticDocument
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace Blomstra\Search\Commands;
|
||||||
use Blomstra\Search\Observe\SavingJob;
|
use Blomstra\Search\Observe\SavingJob;
|
||||||
use Blomstra\Search\Seeders\Seeder;
|
use Blomstra\Search\Seeders\Seeder;
|
||||||
use Elasticsearch\Client;
|
use Elasticsearch\Client;
|
||||||
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Contracts\Queue\Queue;
|
use Illuminate\Contracts\Queue\Queue;
|
||||||
|
|
@ -29,6 +30,11 @@ class RebuildDocumentsCommand extends Command
|
||||||
/** @var Client $client */
|
/** @var Client $client */
|
||||||
$client = $container->make('blomstra.search.elastic');
|
$client = $container->make('blomstra.search.elastic');
|
||||||
|
|
||||||
|
/** @var SettingsRepositoryInterface $settings */
|
||||||
|
$settings = $container->make(SettingsRepositoryInterface::class);
|
||||||
|
|
||||||
|
$analyzer = $settings->get('blomstra-search.analyzer-language', 'english');
|
||||||
|
|
||||||
// Flush the index.
|
// Flush the index.
|
||||||
if ($this->option('flush')) {
|
if ($this->option('flush')) {
|
||||||
$client->indices()->delete([
|
$client->indices()->delete([
|
||||||
|
|
@ -36,7 +42,15 @@ class RebuildDocumentsCommand extends Command
|
||||||
'ignore_unavailable' => true
|
'ignore_unavailable' => true
|
||||||
]);
|
]);
|
||||||
$client->indices()->create([
|
$client->indices()->create([
|
||||||
'index' => $container->make('blomstra.search.elastic_index')
|
'index' => $container->make('blomstra.search.elastic_index'),
|
||||||
|
// 'settings' => [
|
||||||
|
// 'analysis' => [
|
||||||
|
// 'analyzer' => [
|
||||||
|
// 'default' => $analyzer,
|
||||||
|
// 'default_search' => $analyzer
|
||||||
|
// ]
|
||||||
|
// ]
|
||||||
|
// ]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ use Blomstra\Search\Observe\SavingJob;
|
||||||
use Blomstra\Search\Seeders;
|
use Blomstra\Search\Seeders;
|
||||||
use Elasticsearch\ClientBuilder;
|
use Elasticsearch\ClientBuilder;
|
||||||
use Flarum\Foundation\AbstractServiceProvider;
|
use Flarum\Foundation\AbstractServiceProvider;
|
||||||
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Contracts\Events\Dispatcher;
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
use Illuminate\Contracts\Queue\Queue;
|
use Illuminate\Contracts\Queue\Queue;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
|
@ -23,29 +23,28 @@ class Provider extends AbstractServiceProvider
|
||||||
Seeders\CommentSeeder::class,
|
Seeders\CommentSeeder::class,
|
||||||
], 'blomstra.search.seeders');
|
], 'blomstra.search.seeders');
|
||||||
|
|
||||||
$config = $this->container->make('flarum.config') ?? [];
|
/** @var SettingsRepositoryInterface $settings */
|
||||||
$elastic = Arr::get($config, 'elastic', []);
|
$settings = $this->container->make(SettingsRepositoryInterface::class);
|
||||||
|
|
||||||
$this->container->singleton('blomstra.search.elastic', function (Container $container) use ($elastic) {
|
$this->container->singleton('blomstra.search.elastic', function (Container $container) use ($settings) {
|
||||||
$builder = ClientBuilder::create()
|
$builder = ClientBuilder::create()
|
||||||
->setHosts([$elastic['endpoint']])
|
->setHosts([$settings->get('blomstra-search.elastic-endpoint')])
|
||||||
->setLogger($container->make(LoggerInterface::class));
|
->setLogger($container->make(LoggerInterface::class));
|
||||||
|
|
||||||
if ($elastic['api-key'] ?? false) {
|
if ($settings->get('blomstra-search.elastic-username')) {
|
||||||
$builder->setApiKey($elastic['api-id'], $elastic['api-key']);
|
$builder->setBasicAuthentication(
|
||||||
}
|
$settings->get('blomstra-search.elastic-username'),
|
||||||
if ($elastic['username'] ?? false) {
|
$settings->get('blomstra-search.elastic-password')
|
||||||
$builder->setBasicAuthentication($elastic['username'], $elastic['password']);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $builder->build();
|
return $builder->build();
|
||||||
});
|
});
|
||||||
|
|
||||||
$index = env('UUID') ?? Arr::get($elastic, 'index', 'flarum');
|
|
||||||
|
|
||||||
$this->container->instance(
|
$this->container->instance(
|
||||||
'blomstra.search.elastic_index',
|
'blomstra.search.elastic_index',
|
||||||
$index
|
$settings->get('blomstra-search.elastic-index', 'flarum')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue