From 6eb98c6572d4ea95bbdaf67447817213fa1d3afe Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 20 Apr 2020 22:12:00 -0500 Subject: [PATCH] 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. --- app/logical/post_query_builder.rb | 32 ++++++++++---------- app/models/saved_search.rb | 14 ++++----- test/unit/post_query_builder_test.rb | 44 ++++++++++++---------------- 3 files changed, 41 insertions(+), 49 deletions(-) diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index 55e22540d..3003df09a 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -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 diff --git a/app/models/saved_search.rb b/app/models/saved_search.rb index ae59f367f..39b4a687e 100644 --- a/app/models/saved_search.rb +++ b/app/models/saved_search.rb @@ -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 diff --git a/test/unit/post_query_builder_test.rb b/test/unit/post_query_builder_test.rb index c293cfe47..cbcd05b76 100644 --- a/test/unit/post_query_builder_test.rb +++ b/test/unit/post_query_builder_test.rb @@ -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: metatag" do