search: support negated wildcards in post searches.
* Support negated wildcards in searches (e.g. "holding -holding_*") * Raise wildcard limit to matching 25 tags regardless of user level. * Fix wildcards potentially matching empty tags. * Fix wildcard tags being sorted by post count only, and therefore not having a stable ordering when tags have equal post counts. * Fix sidebar to calculate wildcards tags the same way the search does.
This commit is contained in:
@@ -1033,20 +1033,36 @@ class PostQueryBuilder
|
|||||||
return q
|
return q
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_tag(tag, output)
|
def parse_tag_operator(tag)
|
||||||
if tag[0] == "-" && tag.size > 1
|
tag = Tag.normalize_name(tag)
|
||||||
output[:exclude] << tag[1..-1].mb_chars.downcase
|
|
||||||
|
|
||||||
elsif tag[0] == "~" && tag.size > 1
|
|
||||||
output[:include] << tag[1..-1].mb_chars.downcase
|
|
||||||
|
|
||||||
elsif tag =~ /\*/
|
|
||||||
matches = Tag.name_matches(tag).select("name").limit(Danbooru.config.tag_query_limit).order("post_count DESC").map(&:name)
|
|
||||||
matches = ["~no_matches~"] if matches.empty?
|
|
||||||
output[:include] += matches
|
|
||||||
|
|
||||||
|
if tag.starts_with?("-")
|
||||||
|
["-", tag.delete_prefix("-")]
|
||||||
|
elsif tag.starts_with?("~")
|
||||||
|
["~", tag.delete_prefix("~")]
|
||||||
else
|
else
|
||||||
output[:related] << tag.mb_chars.downcase
|
[nil, tag]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_tag(tag, output)
|
||||||
|
operator, tag = parse_tag_operator(tag)
|
||||||
|
|
||||||
|
if tag.include?("*")
|
||||||
|
tags = Tag.wildcard_matches(tag)
|
||||||
|
|
||||||
|
if operator == "-"
|
||||||
|
output[:exclude] += tags
|
||||||
|
else
|
||||||
|
tags = ["~no_matches~"] if tags.empty? # force empty results if wildcard found no matches.
|
||||||
|
output[:include] += tags
|
||||||
|
end
|
||||||
|
elsif operator == "-"
|
||||||
|
output[:exclude] << tag
|
||||||
|
elsif operator == "~"
|
||||||
|
output[:include] << tag
|
||||||
|
else
|
||||||
|
output[:related] << tag
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -279,6 +279,10 @@ class Tag < ApplicationRecord
|
|||||||
name_matches(name).or(alias_matches(name))
|
name_matches(name).or(alias_matches(name))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def wildcard_matches(tag, limit: 25)
|
||||||
|
nonempty.name_matches(tag).order(post_count: :desc, name: :asc).limit(limit).pluck(:name)
|
||||||
|
end
|
||||||
|
|
||||||
def search(params)
|
def search(params)
|
||||||
q = super
|
q = super
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ module PostSetPresenters
|
|||||||
end
|
end
|
||||||
|
|
||||||
def pattern_tags
|
def pattern_tags
|
||||||
Tag.name_matches(post_set.tag_string).order(post_count: :desc).limit(MAX_TAGS).pluck(:name)
|
Tag.wildcard_matches(post_set.tag_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
def saved_search_tags
|
def saved_search_tags
|
||||||
|
|||||||
@@ -1962,6 +1962,18 @@ class PostTest < ActiveSupport::TestCase
|
|||||||
assert_tag_match([post2], "a* bbb")
|
assert_tag_match([post2], "a* bbb")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should "return posts for a negated pattern" do
|
||||||
|
post1 = create(:post, tag_string: "aaa")
|
||||||
|
post2 = create(:post, tag_string: "aaab bbb")
|
||||||
|
post3 = create(:post, tag_string: "bbb ccc")
|
||||||
|
|
||||||
|
assert_tag_match([post3], "-a*")
|
||||||
|
assert_tag_match([post3], "bbb -a*")
|
||||||
|
assert_tag_match([post3], "~bbb -a*")
|
||||||
|
assert_tag_match([post1], "a* -*b")
|
||||||
|
assert_tag_match([post2], "-*c -a*a")
|
||||||
|
end
|
||||||
|
|
||||||
should "return posts for the id:<N> metatag" do
|
should "return posts for the id:<N> metatag" do
|
||||||
posts = FactoryBot.create_list(:post, 3)
|
posts = FactoryBot.create_list(:post, 3)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user