* Add hashtag score for better sorting of autosuggestions * Do not use `~<~` operator with no text_pattern_ops indexmaster^2
@@ -153,9 +153,9 @@ const sortHashtagsByUse = (state, tags) => { | |||||
if (usedA === usedB) { | if (usedA === usedB) { | ||||
return 0; | return 0; | ||||
} else if (usedA && !usedB) { | } else if (usedA && !usedB) { | ||||
return 1; | |||||
} else { | |||||
return -1; | return -1; | ||||
} else { | |||||
return 1; | |||||
} | } | ||||
}); | }); | ||||
}; | }; | ||||
@@ -7,6 +7,7 @@ | |||||
# name :string default(""), not null | # name :string default(""), not null | ||||
# created_at :datetime not null | # created_at :datetime not null | ||||
# updated_at :datetime not null | # updated_at :datetime not null | ||||
# score :integer | |||||
# | # | ||||
class Tag < ApplicationRecord | class Tag < ApplicationRecord | ||||
@@ -78,7 +79,7 @@ class Tag < ApplicationRecord | |||||
pattern = sanitize_sql_like(normalize(term.strip)) + '%' | pattern = sanitize_sql_like(normalize(term.strip)) + '%' | ||||
Tag.where(arel_table[:name].lower.matches(pattern.mb_chars.downcase.to_s)) | Tag.where(arel_table[:name].lower.matches(pattern.mb_chars.downcase.to_s)) | ||||
.order(:name) | |||||
.order(Arel.sql('length(name) ASC, score DESC, name ASC')) | |||||
.limit(limit) | .limit(limit) | ||||
.offset(offset) | .offset(offset) | ||||
end | end | ||||
@@ -48,12 +48,17 @@ class TrendingTags | |||||
redis.zrem(key, tag_id.to_s) | redis.zrem(key, tag_id.to_s) | ||||
else | else | ||||
score = ((observed - expected)**2) / expected | score = ((observed - expected)**2) / expected | ||||
redis.zadd(key, score, tag_id.to_s) | |||||
added = redis.zadd(key, score, tag_id.to_s) | |||||
bump_tag_score!(tag_id) if added == 1 | |||||
end | end | ||||
redis.expire(key, EXPIRE_TRENDS_AFTER) | redis.expire(key, EXPIRE_TRENDS_AFTER) | ||||
end | end | ||||
def bump_tag_score!(tag_id) | |||||
Tag.where(id: tag_id).update_all('score = COALESCE(score, 0) + 1') | |||||
end | |||||
def disallowed_hashtags | def disallowed_hashtags | ||||
return @disallowed_hashtags if defined?(@disallowed_hashtags) | return @disallowed_hashtags if defined?(@disallowed_hashtags) | ||||
@@ -0,0 +1,5 @@ | |||||
class AddScoreToTags < ActiveRecord::Migration[5.2] | |||||
def change | |||||
add_column :tags, :score, :int | |||||
end | |||||
end |
@@ -10,7 +10,7 @@ | |||||
# | # | ||||
# It's strongly recommended that you check this file into your version control system. | # It's strongly recommended that you check this file into your version control system. | ||||
ActiveRecord::Schema.define(version: 2019_07_28_084117) do | |||||
ActiveRecord::Schema.define(version: 2019_07_29_185330) do | |||||
# These are extensions that must be enabled in order to support this database | # These are extensions that must be enabled in order to support this database | ||||
enable_extension "plpgsql" | enable_extension "plpgsql" | ||||
@@ -659,6 +659,7 @@ ActiveRecord::Schema.define(version: 2019_07_28_084117) do | |||||
t.string "name", default: "", null: false | t.string "name", default: "", null: false | ||||
t.datetime "created_at", null: false | t.datetime "created_at", null: false | ||||
t.datetime "updated_at", null: false | t.datetime "updated_at", null: false | ||||
t.integer "score" | |||||
t.index "lower((name)::text)", name: "index_tags_on_name_lower", unique: true | t.index "lower((name)::text)", name: "index_tags_on_name_lower", unique: true | ||||
end | end | ||||