post queries: switch to new post search engine.
Switch to the post search engine using the new PostQuery parser. The new
engine fully supports AND, OR, and NOT operators and grouping expressions
with parentheses.
Highlights:
New OR operator:
* `skirt or dress` (same as `~skirt ~dress`)
Tags can be grouped with parentheses:
* `1girl (skirt or dress)`
* `(blonde_hair blue_eyes) or (red_hair green_eyes)`
* `~(blonde_hair blue_eyes) ~(red_hair green_eyes)` (same as above)
* `(pantyhose or thighhighs) (black_legwear or brown_legwear)`
* `(~pantyhose ~thighhighs) (~black_legwear ~brown_legwear)` (same as above)
Metatags can be OR'd together:
* `user:evazion or fav:evazion`
* `~user:evazion ~fav:evazion`
Wildcard tags can combined with either AND or OR:
* `black_* white_*` (find posts with at least one black_* tag AND one white_* tag)
* `black_* or white_*` (find posts with at least one black_* tag OR one white_* tag)
* `~black_* ~white_*` (same as above)
See 4c7cfc73 for more syntax examples.
Fixes #4949: And+or search?
Fixes #5056: Wildcard searches return unexpected results when combined with OR searches
This commit is contained in:
@@ -8,14 +8,16 @@ module PostSets
|
||||
class Post
|
||||
MAX_PER_PAGE = 200
|
||||
MAX_SIDEBAR_TAGS = 25
|
||||
MAX_WILDCARD_TAGS = PostQueryBuilder::MAX_WILDCARD_TAGS
|
||||
|
||||
attr_reader :page, :format, :tag_string, :query, :normalized_query, :show_votes
|
||||
delegate :post_count, to: :normalized_query
|
||||
attr_reader :page, :format, :tag_string, :query, :post_query, :normalized_query, :show_votes
|
||||
delegate :tag, to: :post_query
|
||||
alias_method :show_votes?, :show_votes
|
||||
|
||||
def initialize(tags, page = 1, per_page = nil, user: CurrentUser.user, format: "html", show_votes: false)
|
||||
@query = PostQueryBuilder.new(tags, user, tag_limit: user.tag_query_limit, safe_mode: CurrentUser.safe_mode?, hide_deleted_posts: user.hide_deleted_posts?)
|
||||
@normalized_query = query.normalized_query
|
||||
@post_query = PostQuery.normalize(tags, current_user: user, tag_limit: user.tag_query_limit, safe_mode: CurrentUser.safe_mode?, hide_deleted_posts: user.hide_deleted_posts?)
|
||||
@normalized_query = post_query.with_implicit_metatags
|
||||
@tag_string = tags
|
||||
@page = page
|
||||
@per_page = per_page
|
||||
@@ -32,13 +34,8 @@ module PostSets
|
||||
end
|
||||
|
||||
def wiki_page
|
||||
return nil unless normalized_query.has_single_tag?
|
||||
@wiki_page ||= WikiPage.undeleted.find_by(title: normalized_query.tags.first.name)
|
||||
end
|
||||
|
||||
def tag
|
||||
return nil unless normalized_query.has_single_tag?
|
||||
@tag ||= Tag.find_by(name: normalized_query.tags.first.name)
|
||||
return nil unless post_query.has_single_tag?
|
||||
@wiki_page ||= WikiPage.undeleted.find_by(title: post_query.tag_name)
|
||||
end
|
||||
|
||||
def artist
|
||||
@@ -48,7 +45,7 @@ module PostSets
|
||||
end
|
||||
|
||||
def pool
|
||||
pool_names = normalized_query.select_metatags(:pool, :ordpool).map(&:value)
|
||||
pool_names = post_query.select_metatags(:pool, :ordpool).map(&:value)
|
||||
name = pool_names.first
|
||||
return nil unless pool_names.size == 1
|
||||
|
||||
@@ -56,7 +53,7 @@ module PostSets
|
||||
end
|
||||
|
||||
def favgroup
|
||||
favgroup_names = normalized_query.select_metatags(:favgroup, :ordfavgroup).map(&:value)
|
||||
favgroup_names = post_query.select_metatags(:favgroup, :ordfavgroup).map(&:value)
|
||||
name = favgroup_names.first
|
||||
return nil unless favgroup_names.size == 1
|
||||
|
||||
@@ -84,7 +81,7 @@ module PostSets
|
||||
end
|
||||
|
||||
def per_page
|
||||
(@per_page || query.find_metatag(:limit) || CurrentUser.user.per_page).to_i.clamp(0, max_per_page)
|
||||
(@per_page || post_query.find_metatag(:limit) || CurrentUser.user.per_page).to_i.clamp(0, max_per_page)
|
||||
end
|
||||
|
||||
def max_per_page
|
||||
@@ -95,11 +92,15 @@ module PostSets
|
||||
@posts ||= normalized_query.paginated_posts(page, includes: includes, count: post_count, search_count: !post_count.nil?, limit: per_page, max_limit: max_per_page).load
|
||||
end
|
||||
|
||||
def post_count
|
||||
normalized_query.post_count
|
||||
end
|
||||
|
||||
def hide_from_crawler?
|
||||
return true if current_page > 50
|
||||
return true if show_votes?
|
||||
return true if artist.present? && artist.is_banned?
|
||||
return false if query.is_empty_search? || query.is_simple_tag? || query.is_metatag?(:order, :rank)
|
||||
return false if post_query.is_empty_search? || post_query.is_simple_tag? || post_query.is_metatag?(:order, :rank)
|
||||
true
|
||||
end
|
||||
|
||||
@@ -118,7 +119,7 @@ module PostSets
|
||||
end
|
||||
|
||||
def show_deleted?
|
||||
query.select_metatags("status").any? do |metatag|
|
||||
post_query.select_metatags("status").any? do |metatag|
|
||||
metatag.value.downcase.in?(%w[all any active unmoderated modqueue deleted appealed])
|
||||
end
|
||||
end
|
||||
@@ -133,13 +134,13 @@ module PostSets
|
||||
|
||||
concerning :TagListMethods do
|
||||
def related_tags
|
||||
if query.is_wildcard_search?
|
||||
if post_query.wildcards.one? && post_query.tags.none?
|
||||
wildcard_tags
|
||||
elsif query.is_metatag?(:search)
|
||||
elsif post_query.is_metatag?(:search)
|
||||
saved_search_tags
|
||||
elsif query.is_empty_search? || query.is_metatag?(:order, :rank)
|
||||
elsif post_query.is_empty_search? || post_query.is_metatag?(:order, :rank)
|
||||
popular_tags.presence || frequent_tags
|
||||
elsif query.is_single_term?
|
||||
elsif post_query.is_single_term?
|
||||
similar_tags.presence || frequent_tags
|
||||
else
|
||||
frequent_tags
|
||||
@@ -151,7 +152,7 @@ module PostSets
|
||||
end
|
||||
|
||||
def similar_tags
|
||||
RelatedTagCalculator.cached_similar_tags_for_search(query.normalized_query(implicit: false), MAX_SIDEBAR_TAGS)
|
||||
RelatedTagCalculator.cached_similar_tags_for_search(post_query, MAX_SIDEBAR_TAGS)
|
||||
end
|
||||
|
||||
def frequent_tags
|
||||
@@ -161,7 +162,7 @@ module PostSets
|
||||
# Wildcard searches can show up to 100 tags in the sidebar, not 25,
|
||||
# because that's how many tags the search itself will use.
|
||||
def wildcard_tags
|
||||
Tag.wildcard_matches(tag_string).limit(PostQueryBuilder::MAX_WILDCARD_TAGS).pluck(:name)
|
||||
Tag.wildcard_matches(post_query.wildcards.first).limit(MAX_WILDCARD_TAGS).pluck(:name)
|
||||
end
|
||||
|
||||
def saved_search_tags
|
||||
|
||||
Reference in New Issue
Block a user