continue refactoring savedsearch

This commit is contained in:
Albert Yi
2018-11-13 18:05:05 -08:00
parent df02eb7951
commit 0508b127fd
17 changed files with 171 additions and 186 deletions

View File

@@ -50,7 +50,7 @@ class SavedSearchesController < ApplicationController
def check_availability
if !SavedSearch.enabled?
raise NotImplementedError.new("Listbooru service is not configured. Saved searches are not available.")
raise NotImplementedError.new("Saved searches are not available.")
end
end

View File

@@ -71,9 +71,9 @@ class PostQueryBuilder
if SavedSearch.enabled?
saved_searches.each do |saved_search|
if saved_search == "all"
post_ids = SavedSearch.post_ids(CurrentUser.id)
post_ids = SavedSearch.post_ids_for(CurrentUser.id)
else
post_ids = SavedSearch.post_ids(CurrentUser.id, saved_search)
post_ids = SavedSearch.post_ids_for(CurrentUser.id, label: saved_search)
end
post_ids = [0] if post_ids.empty?

View File

@@ -1,30 +1,35 @@
class SavedSearch < ApplicationRecord
REDIS_EXPIRY = 3600
QUERY_LIMIT = 500
QUERY_LIMIT = 1000
def self.enabled?
Danbooru.config.redis_url.present?
end
concerning :Redis do
class_methods do
def enabled?
Danbooru.config.redis_url.present?
extend Memoist
def redis
::Redis.new(url: Danbooru.config.redis_url)
end
memoize :redis
def post_ids_for(user_id, label: nil)
redis = Redis.new(url: Danbooru.config.redis_url)
label = normalize_label(label) if label
queries = queries_for(user_id, label: label)
post_ids = Set.new
queries.each do |query|
query_hash = Cache.hash(query)
redis_key = "search:#{query_hash}"
redis_key = "search:#{query}"
if redis.exists(redis_key)
sub_ids = redis.smembers(redis_key)
sub_ids = redis.smembers(redis_key).map(&:to_i)
post_ids.merge(sub_ids)
redis.expire(redis_key, REDIS_EXPIRY)
else
SavedSearch.delay(queue: "default").populate(query)
end
end
post_ids.to_a.sort
post_ids.to_a.sort.last(QUERY_LIMIT)
end
end
end
@@ -52,24 +57,39 @@ class SavedSearch < ApplicationRecord
labels
end
def self.labels_for(user_id)
Cache.get(cache_key(user_id)) do
SavedSearch.
where(user_id: user_id).
order("label").
pluck(Arel.sql("distinct unnest(labels) as label"))
end
def labels_for(user_id)
SavedSearch.
where(user_id: user_id).
order("label").
pluck(Arel.sql("distinct unnest(labels) as label"))
end
end
def normalize_labels
self.labels = labels.
map {|x| SavedSearch.normalize_label(x)}.
reject {|x| x.blank?}
end
def label_string
labels.join(" ")
end
def label_string=(val)
self.labels = val.to_s.split(/[[:space:]]+/)
end
def labels=(labels)
labels = labels.map { |label| SavedSearch.normalize_label(label) }
super(labels)
end
end
concerning :Search do
class_methods do
def populate(query)
CurrentUser.as_system do
query_hash = Cache.hash(query)
redis_key = "search:#{query_hash}"
redis = Redis.new(url: Danbooru.config.redis_url)
redis_key = "search:#{query}"
return if redis.exists(redis_key)
post_ids = Post.tag_match(query, true).limit(QUERY_LIMIT).pluck(:id)
redis.sadd(redis_key, post_ids)
@@ -81,35 +101,37 @@ class SavedSearch < ApplicationRecord
end
end
concerning :Queries do
class_methods do
def queries_for(user_id, label: nil, options: {})
SavedSearch.
where(user_id: user_id).
labeled(label).
pluck(:query).
map {|x| Tag.normalize_query(x, sort: true)}.
sort.
uniq
end
end
def normalized_query
Tag.normalize_query(query, sort: true)
end
def normalize_query
self.query = Tag.normalize_query(query, sort: false)
end
end
attr_accessor :disable_labels
belongs_to :user
validates :query, presence: true
validate :validate_count
before_create :update_user_on_create
after_destroy :update_user_on_destroy
before_validation :normalize
scope :labeled, ->(label) { where("labels @> string_to_array(?, '~~~~')", label)}
def self.queries_for(user_id, label: nil, options: {})
SavedSearch.
where(user_id: user_id).
tap {|arel| label ? arel.labeled(label) : arel}.
pluck(:query).
map {|x| Tag.normalize_query(x, sort: true)}.
sort.
uniq
end
def normalized_query
Tag.normalize_query(query, sort: true)
end
def normalize
self.query = Tag.normalize_query(query, sort: false)
self.labels = labels.
map {|x| SavedSearch.normalize_label(x)}.
reject {|x| x.blank?}
end
before_validation :normalize_query
before_validation :normalize_labels
scope :labeled, ->(label) { label.present? ? where("labels @> string_to_array(?, '~~~~')", label) : where("true") }
def validate_count
if user.saved_searches.count + 1 > user.max_saved_searches
@@ -129,19 +151,6 @@ class SavedSearch < ApplicationRecord
end
end
def label_string
labels.join(" ")
end
def label_string=(val)
self.labels = val.to_s.split(/[[:space:]]+/)
end
def labels=(labels)
labels = labels.map { |label| SavedSearch.normalize_label(label) }
super(labels)
end
def disable_labels=(value)
CurrentUser.update(disable_categorized_saved_searches: true) if value.to_s.truthy?
end

View File

@@ -19,7 +19,7 @@ module PostSetPresenters
if post_set.is_pattern_search?
pattern_tags
elsif post_set.is_saved_search?
SavedSearch.labels_for(CurrentUser.user.id).map {|x| "search:#{x}"}
["search:all"] + SavedSearch.labels_for(CurrentUser.user.id).map {|x| "search:#{x}"}
elsif post_set.is_empty_tag? || post_set.tag_string == "order:rank"
popular_tags
elsif post_set.is_single_tag?