From e4fd3d9850998f8137a07e7c6f3956ec3e11fde6 Mon Sep 17 00:00:00 2001
From: Rafael dos Santos Silva <xfalcox@gmail.com>
Date: Thu, 2 Feb 2023 14:39:44 -0300
Subject: [PATCH] FIX: Better ordering of similar user search suggestions
 (#20142)

* FIX: Better ordering of similar user search suggestions
---
 app/models/user_search.rb       | 21 ++++++++-------------
 spec/models/user_search_spec.rb |  9 +++++++++
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/app/models/user_search.rb b/app/models/user_search.rb
index b89b896ffbd..118e6d9bd1c 100644
--- a/app/models/user_search.rb
+++ b/app/models/user_search.rb
@@ -173,24 +173,19 @@ class UserSearch
 
     return users.to_a if users.size >= @limit
 
-    if SiteSetting.user_search_similar_results
-      # 6. similar usernames
-      if @term.present?
+    # 6. similar usernames / names
+    if @term.present? && SiteSetting.user_search_similar_results
+      if SiteSetting.enable_names?
         scoped_users
-          .where("username_lower <-> ? < 1", @term)
-          .order(["username_lower <-> ? ASC", @term])
+          .where("username_lower <-> ? < 1 OR name <-> ? < 1", @term, @term)
+          .order(["LEAST(username_lower <-> ?, name <-> ?) ASC", @term, @term])
           .limit(@limit - users.size)
           .pluck(:id)
           .each { |id| users << id }
-      end
-
-      return users.to_a if users.size >= @limit
-
-      # 7. similar names
-      if SiteSetting.enable_names? && @term.present?
+      else
         scoped_users
-          .where("name <-> ? < 1", @term)
-          .order(["name <-> ? ASC", @term])
+          .where("username_lower <-> ? < 1", @term)
+          .order(["username_lower <-> ? ASC", @term])
           .limit(@limit - users.size)
           .pluck(:id)
           .each { |id| users << id }
diff --git a/spec/models/user_search_spec.rb b/spec/models/user_search_spec.rb
index dc91ef7f046..175a5ee02dc 100644
--- a/spec/models/user_search_spec.rb
+++ b/spec/models/user_search_spec.rb
@@ -274,6 +274,7 @@ RSpec.describe UserSearch do
       codinghorror = Fabricate(:user, username: "codinghorror", name: "Jeff Atwood")
       pfaffman = Fabricate(:user, username: "pfaffman")
       zogstrip = Fabricate(:user, username: "zogstrip", name: "Régis Hanol")
+      roman = Fabricate(:user, username: "roman", name: "Roman Rizzi")
 
       SiteSetting.user_search_similar_results = false
       expect(UserSearch.new("rafel").search).to be_blank
@@ -297,5 +298,13 @@ RSpec.describe UserSearch do
       expect(UserSearch.new("regis").search).to include(zogstrip)
       expect(UserSearch.new("reg").search).to include(zogstrip)
     end
+
+    it "orders the results by similarity" do
+      zogstrip = Fabricate(:user, username: "zogstrip", name: "Régis Hanol")
+      roman = Fabricate(:user, username: "roman", name: "Roman Rizzi")
+      SiteSetting.user_search_similar_results = true
+
+      expect(UserSearch.new("regis").search.first).to eq(zogstrip)
+    end
   end
 end