diff --git a/app/Libraries/Search/UserSearch.php b/app/Libraries/Search/UserSearch.php index eecc43b9496..528bde4f5cc 100644 --- a/app/Libraries/Search/UserSearch.php +++ b/app/Libraries/Search/UserSearch.php @@ -12,6 +12,11 @@ class UserSearch extends RecordSearch { + private const BOOST_GROUPS = [ + 2 => ['alumni', 'loved', 'beatmap_spotlights', 'tournament_staff'], + 5 => ['ppy', 'gmt', 'nat', 'bng', 'bng_limited', 'dev', 'support', 'featured_artist'], + ]; + public function __construct(?UserSearchParams $params = null) { parent::__construct( @@ -43,6 +48,15 @@ public function getQuery() 'fields' => ['username', 'username._*'], ]; + static $boostGroups; + + if (!isset($boostGroups)) { + $allGroupsByIdentifier = app('groups')->allByIdentifier(); + foreach (self::BOOST_GROUPS as $boost => $identifiers) { + $boostGroups[$boost] = array_reject_null(array_map(fn ($identifier) => ($allGroupsByIdentifier[$identifier] ?? null)?->getKey(), $identifiers)); + } + } + $query = (new BoolQuery()) ->mustNot(['terms' => ['_id' => $this->params->blockedUserIds()]]) ->mustNot(['term' => ['is_old' => true]]) @@ -50,13 +64,18 @@ public function getQuery() ->filter(['term' => ['user_type' => 0]]); if ($this->params->queryString !== null) { - $query->shouldMatch(1) + $query->must((new BoolQuery())->shouldMatch(1) ->should(['term' => ['_id' => ['value' => $this->params->queryString, 'boost' => 100]]]) - ->should(['match' => ['username.raw' => ['query' => $this->params->queryString, 'boost' => 5]]]) + ->should(['match' => ['username.raw' => ['query' => $this->params->queryString, 'boost' => 10]]]) ->should(['match' => ['previous_usernames' => ['query' => $this->params->queryString]]]) ->should(['multi_match' => array_merge(['query' => $this->params->queryString], $lowercaseStick)]) ->should(['multi_match' => array_merge(['query' => $this->params->queryString], $whitespaceStick)]) - ->should(['match_phrase' => ['username._slop' => $this->params->queryString]]); + ->should(['match_phrase' => ['username._slop' => $this->params->queryString]])); + + foreach ($boostGroups as $boost => $groupIds) { + $query->should(['terms' => ['groups' => $groupIds, 'boost' => $boost]]); + } + $query->should(['range' => ['user_lastvisit' => ['gte' => 'now-30d/d', 'boost' => 1.5]]]); } if ($this->params->recentOnly) { diff --git a/app/Models/Traits/Es/UserSearch.php b/app/Models/Traits/Es/UserSearch.php index e6ce6fa2dd9..17b995c84b6 100644 --- a/app/Models/Traits/Es/UserSearch.php +++ b/app/Models/Traits/Es/UserSearch.php @@ -17,6 +17,7 @@ public static function esIndexName() public static function esIndexingQuery() { return static::withoutGlobalScopes() + ->with('userGroups') ->with('usernameChangeHistoryPublic'); } @@ -30,8 +31,9 @@ protected function getEsFieldValue(string $field) return match ($field) { 'id' => $this->getKey(), 'is_old' => $this->isOld(), - 'previous_usernames' => $this->previousUsernames(true)->unique()->values(), + 'previous_usernames' => $this->previousUsernames(true)->unique()->all(), 'user_lastvisit' => $this->displayed_last_visit, + 'groups' => $this->userGroups->pluck('group_id')->all(), default => $this->$field, }; } diff --git a/config/schemas/users.json b/config/schemas/users.json index 27714ec68fb..9595a34465d 100644 --- a/config/schemas/users.json +++ b/config/schemas/users.json @@ -22,6 +22,9 @@ "user_warnings": { "type": "short" }, + "groups": { + "type": "integer" + }, "username": { "type": "text", "fields": {