FEATURE: in:tagged search (srv side) (#7822)

FEATURE: in:tagged search (srv side) (#7822)

  • FEATURE: in:tagged and in:untagged advanced search filters

Similar to in:solved or in:unsolved, the filters check for an existence of the topic_id in the topic_tags table.

see: How to search/filter untagged topics - support - Discourse Meta

diff --git a/lib/search.rb b/lib/search.rb
index aa3bdb0..395ea95 100644
--- a/lib/search.rb
+++ b/lib/search.rb
@@ -265,6 +265,18 @@ class Search
     @advanced_filters
   end
 
+  advanced_filter(/^in:tagged$/) do |posts|
+    posts
+      .where('EXISTS (SELECT 1 FROM topic_tags WHERE topic_tags.topic_id = posts.topic_id)')
+  end
+
+  advanced_filter(/^in:untagged$/) do |posts|
+    posts
+      .joins("LEFT JOIN topic_tags ON
+        topic_tags.topic_id = posts.topic_id")
+      .where("topic_tags.id IS NULL")
+  end
+
   advanced_filter(/^status:open$/) do |posts|
     posts.where('NOT topics.closed AND NOT topics.archived')
   end
diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb
index 7e6e45c..d1d7bde 100644
--- a/spec/components/search_spec.rb
+++ b/spec/components/search_spec.rb
@@ -1377,4 +1377,32 @@ describe Search do
 
   end
 
+  context 'in:tagged' do
+    it 'allows for searching by presence of any tags' do
+      topic = Fabricate(:topic, title: 'I am testing a tagged search')
+      _post = Fabricate(:post, topic: topic, raw: 'this is the first post')
+      tag = Fabricate(:tag)
+      topic_tag = Fabricate(:topic_tag, topic: topic, tag: tag)
+
+      results = Search.execute('in:untagged')
+      expect(results.posts.length).to eq(0)
+
+      results = Search.execute('in:tagged')
+      expect(results.posts.length).to eq(1)
+    end
+  end
+
+  context 'in:untagged' do
+    it 'allows for searching by presence of no tags' do
+      topic = Fabricate(:topic, title: 'I am testing a untagged search')
+      _post = Fabricate(:post, topic: topic, raw: 'this is the first post')
+
+      results = Search.execute('in:untagged')
+      expect(results.posts.length).to eq(1)
+
+      results = Search.execute('in:tagged')
+      expect(results.posts.length).to eq(0)
+    end
+  end
+
 end

GitHub sha: 6c568998

1 Like