0
0
Fork 0

Add more accurate hashtag search (#11579)

* Add more accurate hashtag search

Using ElasticSearch to index hashtags with edge n-grams and score
them by usage within the last 7 days since last activity. Only
hashtags that have been reviewed and are listable can appear in
searches, unless they match the query exactly

* Fix search analyzer dropping non-ascii characters
This commit is contained in:
Eugen Rochko 2019-08-18 03:45:51 +02:00 committed by GitHub
parent 3a77090d01
commit cc0a55cf9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 149 additions and 13 deletions

View file

@ -13,6 +13,8 @@
# listable :boolean
# reviewed_at :datetime
# requested_review_at :datetime
# last_status_at :datetime
# last_trend_at :datetime
#
class Tag < ApplicationRecord
@ -33,7 +35,8 @@ class Tag < ApplicationRecord
scope :unreviewed, -> { where(reviewed_at: nil) }
scope :pending_review, -> { unreviewed.where.not(requested_review_at: nil) }
scope :usable, -> { where(usable: [true, nil]) }
scope :discoverable, -> { where(listable: [true, nil]).joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
scope :listable, -> { where(listable: [true, nil]) }
scope :discoverable, -> { listable.joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) }
delegate :accounts_count,
@ -44,6 +47,8 @@ class Tag < ApplicationRecord
after_save :save_account_tag_stat
update_index('tags#tag', :self) if Chewy.enabled?
def account_tag_stat
super || build_account_tag_stat
end
@ -121,9 +126,10 @@ class Tag < ApplicationRecord
normalized_term = normalize(term.strip).mb_chars.downcase.to_s
pattern = sanitize_sql_like(normalized_term) + '%'
Tag.where(arel_table[:name].lower.matches(pattern))
.where(arel_table[:score].gt(0).or(arel_table[:name].lower.eq(normalized_term)))
.order(Arel.sql('length(name) ASC, score DESC, name ASC'))
Tag.listable
.where(arel_table[:name].lower.matches(pattern))
.where(arel_table[:name].lower.eq(normalized_term).or(arel_table[:reviewed_at].not_eq(nil)))
.order(Arel.sql('length(name) ASC, name ASC'))
.limit(limit)
.offset(offset)
end

View file

@ -17,6 +17,9 @@ class TrendingTags
increment_historical_use!(tag.id, at_time)
increment_unique_use!(tag.id, account.id, at_time)
increment_vote!(tag, at_time)
tag.update(last_status_at: Time.now.utc) if tag.last_status_at.nil? || tag.last_status_at < 12.hours.ago
tag.update(last_trend_at: Time.now.utc) if trending?(tag) && (tag.last_trend_at.nil? || tag.last_trend_at < 12.hours.ago)
end
def get(limit, filtered: true)