about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/models/tag.rb19
-rw-r--r--db/migrate/20170606113804_change_tag_search_index_to_btree.rb12
-rw-r--r--db/schema.rb4
-rw-r--r--spec/models/tag_spec.rb9
4 files changed, 26 insertions, 18 deletions
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 4001e6ed5..08e3c1b03 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -21,22 +21,9 @@ class Tag < ApplicationRecord
   end
 
   class << self
-    def search_for(terms, limit = 5)
-      terms      = Arel.sql(connection.quote(terms.gsub(/['?\\:]/, ' ')))
-      textsearch = 'to_tsvector(\'simple\', tags.name)'
-      query      = 'to_tsquery(\'simple\', \'\'\' \' || ' + terms + ' || \' \'\'\' || \':*\')'
-
-      sql = <<-SQL.squish
-        SELECT
-          tags.*,
-          ts_rank_cd(#{textsearch}, #{query}) AS rank
-        FROM tags
-        WHERE #{query} @@ #{textsearch}
-        ORDER BY rank DESC
-        LIMIT ?
-      SQL
-
-      Tag.find_by_sql([sql, limit])
+    def search_for(term, limit = 5)
+      pattern = sanitize_sql_like(term) + '%'
+      Tag.where('name like ?', pattern).order(:name).limit(limit)
     end
   end
 end
diff --git a/db/migrate/20170606113804_change_tag_search_index_to_btree.rb b/db/migrate/20170606113804_change_tag_search_index_to_btree.rb
new file mode 100644
index 000000000..5248e1720
--- /dev/null
+++ b/db/migrate/20170606113804_change_tag_search_index_to_btree.rb
@@ -0,0 +1,12 @@
+class ChangeTagSearchIndexToBtree < ActiveRecord::Migration[5.1]
+
+  def up
+    remove_index :tags, name: :hashtag_search_index
+    execute 'CREATE INDEX hashtag_search_index ON tags (name text_pattern_ops);'
+  end
+
+  def down
+    remove_index :tags, name: :hashtag_search_index
+    execute 'CREATE INDEX hashtag_search_index ON tags USING gin(to_tsvector(\'simple\', tags.name));'
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index ca904569e..712f62ea6 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20170604144747) do
+ActiveRecord::Schema.define(version: 20170606113804) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -320,7 +320,7 @@ ActiveRecord::Schema.define(version: 20170604144747) do
     t.string "name", default: "", null: false
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
-    t.index "to_tsvector('simple'::regconfig, (name)::text)", name: "hashtag_search_index", using: :gin
+    t.index "name text_pattern_ops", name: "hashtag_search_index"
     t.index ["name"], name: "index_tags_on_name", unique: true
   end
 
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
index 7a5b8ec89..2496946cb 100644
--- a/spec/models/tag_spec.rb
+++ b/spec/models/tag_spec.rb
@@ -22,5 +22,14 @@ RSpec.describe Tag, type: :model do
 
       expect(results).to eq [tag]
     end
+
+    it 'finds the exact matching tag as the first item' do
+      similar_tag = Fabricate(:tag, name: "matchlater")
+      tag = Fabricate(:tag, name: "match")
+
+      results = Tag.search_for("match")
+
+      expect(results).to eq [tag, similar_tag]
+    end
   end
 end