Compare commits
31 Commits
feat/analy
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
e4590f3ea9 | |
|
|
83c0b0e7ec | |
|
|
3a8559ecca | |
|
|
082892f413 | |
|
|
0b9586aee2 | |
|
|
c54d916361 | |
|
|
09c01b3445 | |
|
|
a089698247 | |
|
|
7344fc33b7 | |
|
|
2696fa4dfd | |
|
|
a6d6230553 | |
|
|
f537506166 | |
|
|
a9bb20dfe7 | |
|
|
6417e8e9f4 | |
|
|
22e2796a65 | |
|
|
52168bb5c3 | |
|
|
7f4befd73b | |
|
|
115c06e9bf | |
|
|
d2b8869eb4 | |
|
|
f72acc60ef | |
|
|
fc830ea921 | |
|
|
4538fe2ba8 | |
|
|
5774879331 | |
|
|
3e2f3f9585 | |
|
|
bf90e3279e | |
|
|
bce3258325 | |
|
|
7f282cdb84 | |
|
|
7cb4071a54 | |
|
|
e3dfc04192 | |
|
|
e7e4495306 | |
|
|
bf19eed20f |
25
README.md
25
README.md
|
|
@ -18,9 +18,32 @@ fulltext search with one that is completely relying on the proven elasticsearch
|
|||
## Installation
|
||||
|
||||
```bash
|
||||
composer require blomstra/search:*
|
||||
composer require sbp/flarum-search
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
This fork is now maintained as `sbp/flarum-search`.
|
||||
|
||||
Intentional compatibility leftovers:
|
||||
- settings keys remain `blomstra-search.*`
|
||||
- some translation keys remain `blomstra-search.*`
|
||||
- CLI command names may still remain `blomstra:*` until a later migration
|
||||
|
||||
Search behavior:
|
||||
- title autocomplete enabled
|
||||
- fuzzy title search enabled
|
||||
- exact + fuzzy content search on full search page
|
||||
- no content autocomplete in dropdown (performance decision)
|
||||
``
|
||||
|
||||
Repository can be found here: https://gitea.muehlberger.net/sbp-jm/sbp-flarum-search
|
||||
|
||||
|
||||
|
||||
|
||||
Enable the extension in the admin area and configure the Elasticsearch endpoint and index name in the extension settings.
|
||||
|
||||
## Setting up the index
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "blomstra/search",
|
||||
"name": "sbp/flarum-search",
|
||||
"description": "Replaces Flarum search with one powered by an elastic search server.",
|
||||
"keywords": [
|
||||
"extension",
|
||||
|
|
@ -11,16 +11,20 @@
|
|||
"elasticsearch"
|
||||
],
|
||||
"support": {
|
||||
"email": "helpdesk@blomstra.net",
|
||||
"email": "mueh+git@sbp.de",
|
||||
"forum": "https://blomstra.community/t/ext-search"
|
||||
},
|
||||
"type": "flarum-extension",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "sbp",
|
||||
"email": "info@sbp.de"
|
||||
},
|
||||
{
|
||||
"name": "Team Blomstra",
|
||||
"email": "development@blomstra.net",
|
||||
"role": "Developer"
|
||||
"role": "Original Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
|
|
@ -43,7 +47,7 @@
|
|||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Blomstra\\Search\\": "src/"
|
||||
"Sbp\\Search\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search;
|
||||
namespace Sbp\Search;
|
||||
|
||||
use Flarum\Extend as Flarum;
|
||||
|
||||
|
|
@ -26,8 +26,8 @@ return [
|
|||
new Flarum\Locales(__DIR__.'/resources/locale'),
|
||||
|
||||
(new Flarum\Routes('api'))
|
||||
->get('/blomstra/search/{type}', 'blomstra.search', Api\Controllers\SearchController::class)
|
||||
->put('/blomstra/search/index', 'blomstra.search.index', Api\Controllers\IndexController::class),
|
||||
->get('/sbp/search/{type}', 'sbp.search', Api\Controllers\SearchController::class)
|
||||
->put('/sbp/search/index', 'sbp.search.index', Api\Controllers\IndexController::class),
|
||||
(new Flarum\Console())
|
||||
->command(Commands\BuildCommand::class),
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
(()=>{var a={n:t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return a.d(e,{a:e}),e},d:(t,e)=>{for(var n in e)a.o(e,n)&&!a.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o:(a,t)=>Object.prototype.hasOwnProperty.call(a,t)};(()=>{"use strict";function t(a,e){return t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(a,t){return a.__proto__=t,a},t(a,e)}const e=flarum.core.compat["admin/app"];var n=a.n(e);const r=flarum.core.compat["common/extend"],s=flarum.core.compat["admin/components/DashboardPage"];var i=a.n(s);const l=flarum.core.compat["admin/components/DashboardWidget"];var o=a.n(l);const c=flarum.core.compat["common/components/Alert"];var h=a.n(c),d=function(a){var e,r;function s(){return a.apply(this,arguments)||this}r=a,(e=s).prototype=Object.create(r.prototype),e.prototype.constructor=e,t(e,r);var i=s.prototype;return i.className=function(){return"ReindexWarningWidget"},i.content=function(){return m(h(),{type:"warning",dismissible:!1,icon:"fas fa-exclamation-triangle",title:n().translator.trans("blomstra-search.admin.reindex-required.title")},n().translator.trans("blomstra-search.admin.reindex-required.detail"))},s}(o());n().initializers.add("blomstra-search",function(){var a=n().data.settings["blomstra-search.active-index"],t=n().data.settings["blomstra-search.index-compatible"];a&&"v3"!==t&&(0,r.extend)(i().prototype,"availableWidgets",function(a){a.add("blomstra-search-reindex",m(d),110)}),n().extensionData.for("blomstra-search").registerSetting(function(){var t=n().data.settings["blomstra-search.indexed-analyzer"];if(!a||!t)return null;var e=this.setting("blomstra-search.analyzer-language")()||"english",r=this.setting("blomstra-search.stem-exclusion")()||"",s=n().data.settings["blomstra-search.indexed-stem-exclusion"]||"";return e===t&&r===s?null:m(h(),{type:"warning",dismissible:!1,icon:"fas fa-exclamation-triangle"},n().translator.trans("blomstra-search.admin.index-settings-changed"))}).registerSetting({setting:"blomstra-search.elastic-endpoint",label:n().translator.trans("blomstra-search.admin.elastic-endpoint"),type:"input"}).registerSetting({setting:"blomstra-search.elastic-username",label:n().translator.trans("blomstra-search.admin.elastic-username"),type:"input"}).registerSetting({setting:"blomstra-search.elastic-password",label:n().translator.trans("blomstra-search.admin.elastic-password"),type:"password"}).registerSetting({setting:"blomstra-search.elastic-index",label:n().translator.trans("blomstra-search.admin.elastic-index"),default:"flarum",type:"input"}).registerSetting({setting:"blomstra-search.search-discussion-subjects",label:n().translator.trans("blomstra-search.admin.search-discussion-subjects"),type:"switch"}).registerSetting({setting:"blomstra-search.search-post-bodies",label:n().translator.trans("blomstra-search.admin.search-post-bodies"),type:"switch"}).registerSetting({setting:"blomstra-search.analyzer-language",label:n().translator.trans("blomstra-search.admin.analyzer.label"),help:n().translator.trans("blomstra-search.admin.analyzer.help"),type:"select",options:{arabic:"Arabic",armenian:"Armenian",basque:"Basque",bengali:"Bengali",brazilian:"Brazilian Portuguese",bulgarian:"Bulgarian",catalan:"Catalan",cjk:"CJK (Chinese, Japanese, Korean)",czech:"Czech",danish:"Danish",dutch:"Dutch",english:"English",estonian:"Estonian",finnish:"Finnish",french:"French",galician:"Galician",german:"German",greek:"Greek",hindi:"Hindi",hungarian:"Hungarian",indonesian:"Indonesian",irish:"Irish",italian:"Italian",latvian:"Latvian",lithuanian:"Lithuanian",norwegian:"Norwegian",persian:"Persian",portuguese:"Portuguese",romanian:"Romanian",russian:"Russian",sorani:"Sorani (Kurdish)",spanish:"Spanish",swedish:"Swedish",turkish:"Turkish",thai:"Thai"},default:"english"}).registerSetting(function(){var a="cjk"===(this.setting("blomstra-search.analyzer-language")()||"english");return this.buildSettingComponent({setting:"blomstra-search.stem-exclusion",type:"textarea",label:n().translator.trans("blomstra-search.admin.settings.stem-exclusion.label"),help:n().translator.trans("blomstra-search.admin.settings.stem-exclusion.help"),disabled:a})}).registerSetting(function(){var a="cjk"===(this.setting("blomstra-search.analyzer-language")()||"english");return this.buildSettingComponent({setting:"blomstra-search.min-search-length",label:n().translator.trans("blomstra-search.admin.min-search-length.label"),help:n().translator.trans("blomstra-search.admin.min-search-length.help"),type:"select",options:{1:"1",2:"2",3:"3",4:"4"},default:n().data.settings["blomstra-search.min-search-length"],disabled:a})})})})(),module.exports={}})();
|
||||
(()=>{var a={n:t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return a.d(e,{a:e}),e},d:(t,e)=>{for(var n in e)a.o(e,n)&&!a.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o:(a,t)=>Object.prototype.hasOwnProperty.call(a,t)};(()=>{"use strict";function t(a,e){return t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(a,t){return a.__proto__=t,a},t(a,e)}const e=flarum.core.compat["admin/app"];var n=a.n(e);const r=flarum.core.compat["common/extend"],s=flarum.core.compat["admin/components/DashboardPage"];var i=a.n(s);const l=flarum.core.compat["admin/components/DashboardWidget"];var o=a.n(l);const c=flarum.core.compat["common/components/Alert"];var h=a.n(c),d=function(a){var e,r;function s(){return a.apply(this,arguments)||this}r=a,(e=s).prototype=Object.create(r.prototype),e.prototype.constructor=e,t(e,r);var i=s.prototype;return i.className=function(){return"ReindexWarningWidget"},i.content=function(){return m(h(),{type:"warning",dismissible:!1,icon:"fas fa-exclamation-triangle",title:n().translator.trans("blomstra-search.admin.reindex-required.title")},n().translator.trans("blomstra-search.admin.reindex-required.detail"))},s}(o());n().initializers.add("sbp-search",function(){var a=n().data.settings["blomstra-search.active-index"],t=n().data.settings["blomstra-search.index-compatible"];a&&"v3"!==t&&(0,r.extend)(i().prototype,"availableWidgets",function(a){a.add("blomstra-search-reindex",m(d),110)}),n().extensionData.for("sbp-search").registerSetting(function(){var t=n().data.settings["blomstra-search.indexed-analyzer"];if(!a||!t)return null;var e=this.setting("blomstra-search.analyzer-language")()||"english",r=this.setting("blomstra-search.stem-exclusion")()||"",s=n().data.settings["blomstra-search.indexed-stem-exclusion"]||"";return e===t&&r===s?null:m(h(),{type:"warning",dismissible:!1,icon:"fas fa-exclamation-triangle"},n().translator.trans("blomstra-search.admin.index-settings-changed"))}).registerSetting({setting:"blomstra-search.elastic-endpoint",label:n().translator.trans("blomstra-search.admin.elastic-endpoint"),type:"input"}).registerSetting({setting:"blomstra-search.elastic-username",label:n().translator.trans("blomstra-search.admin.elastic-username"),type:"input"}).registerSetting({setting:"blomstra-search.elastic-password",label:n().translator.trans("blomstra-search.admin.elastic-password"),type:"password"}).registerSetting({setting:"blomstra-search.elastic-index",label:n().translator.trans("blomstra-search.admin.elastic-index"),default:"flarum",type:"input"}).registerSetting({setting:"blomstra-search.search-discussion-subjects",label:n().translator.trans("blomstra-search.admin.search-discussion-subjects"),type:"switch"}).registerSetting({setting:"blomstra-search.search-post-bodies",label:n().translator.trans("blomstra-search.admin.search-post-bodies"),type:"switch"}).registerSetting({setting:"blomstra-search.analyzer-language",label:n().translator.trans("blomstra-search.admin.analyzer.label"),help:n().translator.trans("blomstra-search.admin.analyzer.help"),type:"select",options:{arabic:"Arabic",armenian:"Armenian",basque:"Basque",bengali:"Bengali",brazilian:"Brazilian Portuguese",bulgarian:"Bulgarian",catalan:"Catalan",cjk:"CJK (Chinese, Japanese, Korean)",czech:"Czech",danish:"Danish",dutch:"Dutch",english:"English",estonian:"Estonian",finnish:"Finnish",french:"French",galician:"Galician",german:"German",greek:"Greek",hindi:"Hindi",hungarian:"Hungarian",indonesian:"Indonesian",irish:"Irish",italian:"Italian",latvian:"Latvian",lithuanian:"Lithuanian",norwegian:"Norwegian",persian:"Persian",portuguese:"Portuguese",romanian:"Romanian",russian:"Russian",sorani:"Sorani (Kurdish)",spanish:"Spanish",standard:"Standard (generic)",swedish:"Swedish",turkish:"Turkish",thai:"Thai"},default:"english"}).registerSetting(function(){var a="cjk"===(this.setting("blomstra-search.analyzer-language")()||"english");return this.buildSettingComponent({setting:"blomstra-search.stem-exclusion",type:"textarea",label:n().translator.trans("blomstra-search.admin.settings.stem-exclusion.label"),help:n().translator.trans("blomstra-search.admin.settings.stem-exclusion.help"),disabled:a})}).registerSetting(function(){var a="cjk"===(this.setting("blomstra-search.analyzer-language")()||"english");return this.buildSettingComponent({setting:"blomstra-search.min-search-length",label:n().translator.trans("blomstra-search.admin.min-search-length.label"),help:n().translator.trans("blomstra-search.admin.min-search-length.help"),type:"select",options:{1:"1",2:"2",3:"3",4:"4"},default:n().data.settings["blomstra-search.min-search-length"],disabled:a})})})})(),module.exports={}})();
|
||||
//# sourceMappingURL=admin.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -25,7 +25,7 @@ class ReindexWarningWidget extends DashboardWidget {
|
|||
}
|
||||
}
|
||||
|
||||
app.initializers.add('blomstra-search', () => {
|
||||
app.initializers.add('sbp-search', () => {
|
||||
const activeIndex = app.data.settings['blomstra-search.active-index'];
|
||||
const compatVersion = app.data.settings['blomstra-search.index-compatible'];
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ app.initializers.add('blomstra-search', () => {
|
|||
};
|
||||
|
||||
app.extensionData
|
||||
.for('blomstra-search')
|
||||
.for('sbp-search')
|
||||
.registerSetting(function (this: any) {
|
||||
// No index yet, or first build predates this tracking — stay silent.
|
||||
const indexedAnalyzer = app.data.settings['blomstra-search.indexed-analyzer'];
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ import DiscussionListState from 'flarum/forum/states/DiscussionListState';
|
|||
|
||||
export default function extendDiscussionState() {
|
||||
override(DiscussionListState.prototype, 'loadPage', async function (this: DiscussionListState, original, page: number = 1) {
|
||||
const preloaded = app.data.apiDocument || null;
|
||||
|
||||
// If existing payload is given or no search is made, fallback on native page.
|
||||
if (preloaded || !this.requestParams()?.filter?.q) return original.call(this, page);
|
||||
if (!this.requestParams()?.filter?.q) return original.call(this, page);
|
||||
|
||||
const params = this.requestParams();
|
||||
params.page = {
|
||||
|
|
@ -17,18 +16,13 @@ export default function extendDiscussionState() {
|
|||
...params.page,
|
||||
};
|
||||
|
||||
// Default to latest sort when searching without an explicit sort parameter.
|
||||
// Matches the backend default and keeps the dropdown label in sync.
|
||||
if (!params.sort) {
|
||||
params.sort = '-lastPostedAt';
|
||||
}
|
||||
|
||||
if (Array.isArray(params.include)) {
|
||||
params.include = params.include.join(',');
|
||||
}
|
||||
|
||||
// Construct API search URI
|
||||
const url = `${app.forum.attribute('apiUrl')}/blomstra/search/${this.type}`;
|
||||
const url = `${app.forum.attribute('apiUrl')}/sbp/search/${this.type}`;
|
||||
|
||||
// Make API GET request
|
||||
const results = await app.request({ params, url, method: 'GET' });
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@ export default class DiscussionsSearchSource implements SearchSource {
|
|||
async search(query: string): Promise<void> {
|
||||
// Suppress ES instant results when "search within comments" is ON;
|
||||
// only usernames are shown in that mode.
|
||||
if (app.forum.attribute('blomstraSearchPostBodies')) {
|
||||
return;
|
||||
}
|
||||
|
||||
query = query.toLowerCase();
|
||||
|
||||
|
|
@ -38,7 +35,7 @@ export default class DiscussionsSearchSource implements SearchSource {
|
|||
};
|
||||
|
||||
// Construct API search URI
|
||||
const url = `${app.forum.attribute('apiUrl')}/blomstra/search/${this.type}`;
|
||||
const url = `${app.forum.attribute('apiUrl')}/sbp/search/${this.type}`;
|
||||
|
||||
// Make API GET request
|
||||
const results = await app.request({ params, url, method: 'GET' });
|
||||
|
|
@ -72,7 +69,7 @@ export default class DiscussionsSearchSource implements SearchSource {
|
|||
return [
|
||||
<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, sort: 'latest' })}>
|
||||
<LinkButton icon="fas fa-search" href={app.route('index', { q: query })}>
|
||||
{app.translator.trans('core.forum.search.all_discussions_button', { query })}
|
||||
</LinkButton>
|
||||
</li>,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Api;
|
||||
namespace Sbp\Search\Api;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Api\Controllers;
|
||||
namespace Sbp\Search\Api\Controllers;
|
||||
|
||||
use Blomstra\Search\Commands\BuildCommand;
|
||||
use Sbp\Search\Commands\BuildCommand;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Api\Controllers;
|
||||
namespace Sbp\Search\Api\Controllers;
|
||||
|
||||
use Blomstra\Search\Elasticsearch\HasChildQuery;
|
||||
use Blomstra\Search\Elasticsearch\MatchPhraseQuery;
|
||||
use Blomstra\Search\Elasticsearch\MatchQuery;
|
||||
use Blomstra\Search\Elasticsearch\TermsQuery;
|
||||
use Blomstra\Search\Searchers\CommentPostSearcher;
|
||||
use Blomstra\Search\Searchers\DiscussionSearcher;
|
||||
use Blomstra\Search\Searchers\Searcher;
|
||||
use Sbp\Search\Elasticsearch\HasChildQuery;
|
||||
use Sbp\Search\Elasticsearch\MatchPhraseQuery;
|
||||
use Sbp\Search\Elasticsearch\MatchQuery;
|
||||
use Sbp\Search\Elasticsearch\TermsQuery;
|
||||
use Sbp\Search\Searchers\CommentPostSearcher;
|
||||
use Sbp\Search\Searchers\DiscussionSearcher;
|
||||
use Sbp\Search\Searchers\Searcher;
|
||||
use Elasticsearch\Client;
|
||||
use Flarum\Api\Controller\ListDiscussionsController;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
|
|
@ -37,7 +37,7 @@ use Illuminate\Support\Str;
|
|||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Spatie\ElasticsearchQueryBuilder\Builder;
|
||||
use Blomstra\Search\Elasticsearch\BoolQuery;
|
||||
use Sbp\Search\Elasticsearch\BoolQuery;
|
||||
use Spatie\ElasticsearchQueryBuilder\Queries\TermQuery;
|
||||
use Spatie\ElasticsearchQueryBuilder\Sorts\Sort;
|
||||
use Tobscure\JsonApi\Document;
|
||||
|
|
@ -176,7 +176,7 @@ class SearchController extends ListDiscussionsController
|
|||
});
|
||||
|
||||
$document->addPaginationLinks(
|
||||
$this->uri->to('api')->route('blomstra.search', ['type' => 'discussions']),
|
||||
$this->uri->to('api')->route('sbp.search', ['type' => 'discussions']),
|
||||
$request->getQueryParams(),
|
||||
$offset,
|
||||
$limit,
|
||||
|
|
@ -265,7 +265,7 @@ class SearchController extends ListDiscussionsController
|
|||
]);
|
||||
|
||||
$document->addPaginationLinks(
|
||||
$this->uri->to('api')->route('blomstra.search', ['type' => 'discussions']),
|
||||
$this->uri->to('api')->route('sbp.search', ['type' => 'discussions']),
|
||||
$request->getQueryParams(),
|
||||
$offset,
|
||||
$limit,
|
||||
|
|
@ -294,11 +294,30 @@ class SearchController extends ListDiscussionsController
|
|||
return $discussions;
|
||||
}
|
||||
|
||||
protected function buildAutocompleteQuery(string $search): MatchQuery
|
||||
|
||||
protected function buildAutocompleteQuery(string $search): BoolQuery
|
||||
{
|
||||
return (new MatchQuery('title.autocomplete', $search))
|
||||
$query = BoolQuery::create();
|
||||
|
||||
// Title prefix match (stronger)
|
||||
$query->add(
|
||||
(new MatchQuery('title.autocomplete', $search))
|
||||
->operator('and')
|
||||
->boost(1.0);
|
||||
->boost(1.0),
|
||||
'should'
|
||||
);
|
||||
|
||||
// Content prefix match (weaker)
|
||||
$query->add(
|
||||
(new MatchQuery('content.autocomplete', $search))
|
||||
->operator('and')
|
||||
->boost(0.4),
|
||||
'should'
|
||||
);
|
||||
|
||||
$query->minimumShouldMatch(1);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -317,6 +336,31 @@ class SearchController extends ListDiscussionsController
|
|||
protected function buildTextQuery(string $search, User $actor, bool $needsScoring = false): BoolQuery
|
||||
{
|
||||
$textQuery = BoolQuery::create();
|
||||
// Strong direct title match for the full search page.
|
||||
$textQuery->add(
|
||||
(new MatchQuery('title', $search))
|
||||
->operator('and')
|
||||
->boost(4.0),
|
||||
'should'
|
||||
);
|
||||
|
||||
// Low-weight prefix match on title.autocomplete for partial title hits.
|
||||
$textQuery->add(
|
||||
(new MatchQuery('title.autocomplete', $search))
|
||||
->operator('and')
|
||||
->boost(0.35),
|
||||
'should'
|
||||
);
|
||||
|
||||
// Low-weight prefix match on title.autocomplete for the full search page.
|
||||
// Exact / normal title matches should still rank higher than prefix-only hits.
|
||||
$textQuery->add(
|
||||
(new MatchQuery('title.autocomplete', $search))
|
||||
->operator('and')
|
||||
->boost(0.35),
|
||||
'should'
|
||||
);
|
||||
|
||||
|
||||
if ($this->discussionSearcher?->enabled()) {
|
||||
$textQuery->add($this->buildShouldClauses($search, $this->discussionSearcher->boost()), 'should');
|
||||
|
|
@ -352,6 +396,7 @@ class SearchController extends ListDiscussionsController
|
|||
}
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Commands;
|
||||
namespace Sbp\Search\Commands;
|
||||
|
||||
use Blomstra\Search\Jobs\Job;
|
||||
use Blomstra\Search\Jobs\UpdateSearchJob;
|
||||
use Blomstra\Search\Seeders\Seeder;
|
||||
use Sbp\Search\Jobs\Job;
|
||||
use Sbp\Search\Jobs\UpdateSearchJob;
|
||||
use Sbp\Search\Seeders\Seeder;
|
||||
use Elasticsearch\Client;
|
||||
use Elasticsearch\Common\Exceptions\ElasticsearchException;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
|
|
@ -581,29 +581,42 @@ HELP;
|
|||
];
|
||||
}
|
||||
|
||||
$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' => ['type' => 'text', 'analyzer' => 'flarum_analyzer'],
|
||||
'content' => $contentMapping,
|
||||
'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'],
|
||||
'user_id' => ['type' => 'integer'],
|
||||
'groups' => ['type' => 'keyword'],
|
||||
'comment_count' => ['type' => 'integer'],
|
||||
'view_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)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
class BoolQuery extends \Spatie\ElasticsearchQueryBuilder\Queries\BoolQuery
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
use Spatie\ElasticsearchQueryBuilder\Queries\Query;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
use Spatie\ElasticsearchQueryBuilder\Queries\MatchQuery;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
class MatchQuery extends \Spatie\ElasticsearchQueryBuilder\Queries\MatchQuery
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
use Spatie\ElasticsearchQueryBuilder\Queries\Query;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
use Spatie\ElasticsearchQueryBuilder\Queries\Query;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Elasticsearch;
|
||||
namespace Sbp\Search\Elasticsearch;
|
||||
|
||||
class WildcardQuery extends \Spatie\ElasticsearchQueryBuilder\Queries\WildcardQuery
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Exceptions;
|
||||
namespace Sbp\Search\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Jobs;
|
||||
namespace Sbp\Search\Jobs;
|
||||
|
||||
use Elasticsearch\Client;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Jobs;
|
||||
namespace Sbp\Search\Jobs;
|
||||
|
||||
use Blomstra\Search\Seeders\Seeder;
|
||||
use Sbp\Search\Seeders\Seeder;
|
||||
use Flarum\Queue\AbstractJob;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Jobs;
|
||||
namespace Sbp\Search\Jobs;
|
||||
|
||||
use Blomstra\Search\Exceptions\SeedingException;
|
||||
use Sbp\Search\Exceptions\SeedingException;
|
||||
use Elasticsearch\Client;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Jobs;
|
||||
namespace Sbp\Search\Jobs;
|
||||
|
||||
use Elasticsearch\Client;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search;
|
||||
namespace Sbp\Search;
|
||||
|
||||
use Blomstra\Search\Jobs\DeletingJob;
|
||||
use Blomstra\Search\Jobs\Job;
|
||||
use Blomstra\Search\Jobs\UpdateSearchJob;
|
||||
use Blomstra\Search\Jobs\ViewsSearchJob;
|
||||
use Sbp\Search\Jobs\DeletingJob;
|
||||
use Sbp\Search\Jobs\Job;
|
||||
use Sbp\Search\Jobs\UpdateSearchJob;
|
||||
use Sbp\Search\Jobs\ViewsSearchJob;
|
||||
use Elasticsearch\Client as Elastic;
|
||||
use Elasticsearch\ClientBuilder;
|
||||
use Flarum\Api\Client;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Save;
|
||||
namespace Sbp\Search\Save;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Searchers;
|
||||
namespace Sbp\Search\Searchers;
|
||||
|
||||
use Blomstra\Search\Seeders\CommentSeeder;
|
||||
use Sbp\Search\Seeders\CommentSeeder;
|
||||
|
||||
class CommentPostSearcher extends Searcher
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Searchers;
|
||||
namespace Sbp\Search\Searchers;
|
||||
|
||||
use Blomstra\Search\Seeders\DiscussionSeeder;
|
||||
use Sbp\Search\Seeders\DiscussionSeeder;
|
||||
|
||||
class DiscussionSearcher extends Searcher
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Searchers;
|
||||
namespace Sbp\Search\Searchers;
|
||||
|
||||
use Blomstra\Search\Seeders\Seeder;
|
||||
use Sbp\Search\Seeders\Seeder;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
|
||||
abstract class Searcher
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Seeders;
|
||||
namespace Sbp\Search\Seeders;
|
||||
|
||||
use Blomstra\Search\Save\Document;
|
||||
use Sbp\Search\Save\Document;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Discussion\Discussion;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Seeders;
|
||||
namespace Sbp\Search\Seeders;
|
||||
|
||||
use Blomstra\Search\Save\Document;
|
||||
use Sbp\Search\Save\Document;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Discussion\Event as Core;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Blomstra\Search\Seeders;
|
||||
namespace Sbp\Search\Seeders;
|
||||
|
||||
use Blomstra\Search\Save\Document;
|
||||
use Sbp\Search\Save\Document;
|
||||
use Flarum\Extension\ExtensionManager;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
|
|
|||
Loading…
Reference in New Issue