search: clean up saved search: metatag.

* Fix not being able to negate the search: metatag.
* Fix not being able to use the search: metatag twice in the same search.
This commit is contained in:
evazion
2020-04-20 22:12:00 -05:00
parent f6fb3c0169
commit 6eb98c6572
3 changed files with 41 additions and 49 deletions

View File

@@ -38,6 +38,7 @@ class PostQueryBuilder
-filetype filetype
-disapproved disapproved
-parent parent
-search search
md5
width
height
@@ -53,7 +54,6 @@ class PostQueryBuilder
tagcount
child
pixiv_id pixiv
search
embedded
] + TagCategory.short_name_list.map {|x| "#{x}tags"} + COUNT_METATAGS + COUNT_METATAG_SYNONYMS
@@ -156,19 +156,13 @@ class PostQueryBuilder
relation
end
def add_saved_search_relation(saved_searches, relation)
saved_searches.each do |saved_search|
if saved_search == "all"
post_ids = SavedSearch.post_ids_for(CurrentUser.id)
else
post_ids = SavedSearch.post_ids_for(CurrentUser.id, label: saved_search)
end
post_ids = [0] if post_ids.empty?
relation = relation.where("posts.id": post_ids)
def saved_search_matches(label)
case label.downcase
when "all"
Post.where(id: SavedSearch.post_ids_for(CurrentUser.id))
else
Post.where(id: SavedSearch.post_ids_for(CurrentUser.id, label: label))
end
relation
end
def status_matches(status)
@@ -348,8 +342,12 @@ class PostQueryBuilder
relation = relation.merge(commentary_matches(query))
end
if q[:saved_searches]
relation = add_saved_search_relation(q[:saved_searches], relation)
q[:saved_searches_neg].to_a.each do |query|
relation = relation.merge(saved_search_matches(query).negate)
end
q[:saved_searches].to_a.each do |query|
relation = relation.merge(saved_search_matches(query))
end
q[:user_neg].to_a.each do |username|
@@ -886,6 +884,10 @@ class PostQueryBuilder
q[:commentary] ||= []
q[:commentary] << g2
when "-search"
q[:saved_searches_neg] ||= []
q[:saved_searches_neg] << g2
when "search"
q[:saved_searches] ||= []
q[:saved_searches] << g2

View File

@@ -14,7 +14,6 @@ class SavedSearch < ApplicationRecord
memoize :redis
def post_ids_for(user_id, label: nil)
label = normalize_label(label) if label
queries = queries_for(user_id, label: label)
post_ids = Set.new
queries.each do |query|
@@ -135,13 +134,10 @@ class SavedSearch < ApplicationRecord
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| PostQueryBuilder.normalize_query(x, sort: true)}
.sort
.uniq
searches = SavedSearch.where(user_id: user_id)
searches = searches.labeled(label) if label.present?
queries = searches.pluck(:query).map { |query| PostQueryBuilder.normalize_query(query, sort: true) }
queries.sort.uniq
end
end
@@ -160,7 +156,7 @@ class SavedSearch < ApplicationRecord
validate :validate_count
before_validation :normalize_query
before_validation :normalize_labels
scope :labeled, ->(label) { label.present? ? where("labels @> string_to_array(?, '~~~~')", label) : where("true") }
scope :labeled, ->(label) { where_array_includes_any_lower(:labels, [normalize_label(label)]) }
def validate_count
if user.saved_searches.count + 1 > user.max_saved_searches

View File

@@ -597,34 +597,28 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
assert_tag_match([post], "pixiv_id:none")
end
context "saved searches" do
setup do
@post1 = create(:post, tag_string: "aaa")
@post2 = create(:post, tag_string: "bbb")
create(:saved_search, query: "aaa", labels: ["zzz"], user: CurrentUser.user)
create(:saved_search, query: "bbb", user: CurrentUser.user)
end
should "return posts for the search: metatag" do
@post1 = create(:post, tag_string: "aaa")
@post2 = create(:post, tag_string: "bbb")
create(:saved_search, query: "aaa", labels: ["zzz"], user: CurrentUser.user)
create(:saved_search, query: "bbb", user: CurrentUser.user)
context "labeled" do
should "work" do
SavedSearch.expects(:post_ids_for).with(CurrentUser.id, label: "zzz").returns([@post1.id])
assert_tag_match([@post1], "search:zzz")
end
end
Redis.any_instance.stubs(:exists).with("search:aaa").returns(true)
Redis.any_instance.stubs(:exists).with("search:bbb").returns(true)
Redis.any_instance.stubs(:smembers).with("search:aaa").returns([@post1.id])
Redis.any_instance.stubs(:smembers).with("search:bbb").returns([@post2.id])
context "missing" do
should "work" do
SavedSearch.expects(:post_ids_for).with(CurrentUser.id, label: "uncategorized").returns([@post2.id])
assert_tag_match([@post2], "search:uncategorized")
end
end
assert_tag_match([@post1], "search:zzz")
assert_tag_match([@post1], "search:ZZZ")
assert_tag_match([@post2, @post1], "search:all")
assert_tag_match([@post2, @post1], "search:ALL")
assert_tag_match([], "search:does_not_exist")
context "all" do
should "work" do
SavedSearch.expects(:post_ids_for).with(CurrentUser.id).returns([@post1.id, @post2.id])
assert_tag_match([@post2, @post1], "search:all")
end
end
assert_tag_match([@post2], "-search:zzz")
assert_tag_match([@post2], "-search:ZZZ")
assert_tag_match([], "-search:all")
assert_tag_match([], "-search:ALL")
assert_tag_match([@post2, @post1], "-search:does_not_exist")
end
should "return posts for a rating:<s|q|e> metatag" do