search: move misc search parsing helpers to PostQueryBuilder.

* Move various search parser helper methods (`has_metatag?`,
  `is_single_tag?` et al) from PostSets and the Tag model to
  PostQueryBuilder.

* Fix various minor bugs stemming from trying to check if a search query
  contains certain metatags using regexes or other adhoc techniques.
This commit is contained in:
evazion
2020-04-23 01:51:30 -05:00
parent 3dab648d0e
commit dd0d9dff4a
15 changed files with 114 additions and 147 deletions

View File

@@ -1069,7 +1069,7 @@ class Post < ApplicationRecord
def fast_count(tags = "", timeout: 1_000, raise_on_timeout: false, skip_cache: false)
tags = tags.to_s
tags += " rating:s" if CurrentUser.safe_mode?
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && !Tag.has_metatag?(tags, "status", "-status")
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && !PostQueryBuilder.new(tags).has_metatag?("status", "-status")
tags = PostQueryBuilder.new(tags).normalize_query
# Optimize some cases. these are just estimates but at these
@@ -1135,7 +1135,7 @@ class Post < ApplicationRecord
end
def get_count_from_cache(tags)
if Tag.is_simple_tag?(tags)
if PostQueryBuilder.new(tags).is_simple_tag?
count = Tag.find_by(name: tags).try(:post_count)
else
# this will only have a value for multi-tag searches or single metatag searches

View File

@@ -227,40 +227,6 @@ class Tag < ApplicationRecord
end
end
module ParseMethods
# true if query is a single "simple" tag (not a metatag, negated tag, or wildcard tag).
def is_simple_tag?(query)
is_single_tag?(query) && !is_metatag?(query) && !is_negated_tag?(query) && !is_optional_tag?(query) && !is_wildcard_tag?(query)
end
def is_single_tag?(query)
PostQueryBuilder.new(query).split_query.size == 1
end
def is_metatag?(tag)
has_metatag?(tag, *PostQueryBuilder::METATAGS)
end
def is_negated_tag?(tag)
tag.starts_with?("-")
end
def is_optional_tag?(tag)
tag.starts_with?("~")
end
def is_wildcard_tag?(tag)
tag.include?("*")
end
def has_metatag?(tags, *metatags)
return nil if tags.blank?
tags = PostQueryBuilder.new(tags.to_str).split_query if tags.respond_to?(:to_str)
tags.grep(/\A(?:#{metatags.map(&:to_s).join("|")}):(.+)\z/i) { $1 }.first
end
end
module SearchMethods
# ref: https://www.postgresql.org/docs/current/static/pgtrgm.html#idm46428634524336
def order_similarity(name)
@@ -393,6 +359,5 @@ class Tag < ApplicationRecord
include ApiMethods
include CountMethods
include CategoryMethods
extend ParseMethods
extend SearchMethods
end

View File

@@ -237,7 +237,7 @@ class Upload < ApplicationRecord
include SourceMethods
def assign_rating_from_tags
if rating = Tag.has_metatag?(tag_string, :rating)
if rating = PostQueryBuilder.new(tag_string).find_metatag(:rating)
self.rating = rating.downcase.first
end
end