From c6239513063c184ec2d45c07d1b4d47d1208c5a4 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Wed, 8 Mar 2017 22:46:23 +0800 Subject: [PATCH] FEATURE: Search can be scoped to posts that the current user has seen/unseen. https://meta.discourse.org/t/advanced-search-posts-that-i-have-seen/57966 --- lib/search.rb | 28 ++++++++++++++++++++-- spec/components/search_spec.rb | 44 ++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/lib/search.rb b/lib/search.rb index ef306765709..4242ab78c6c 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -315,6 +315,29 @@ class Search end end + advanced_filter(/in:seen/) do |posts| + if @guardian.user + posts + .joins("INNER JOIN post_timings ON + post_timings.topic_id = posts.topic_id + AND post_timings.post_number = posts.post_number + AND post_timings.user_id = #{Post.sanitize(@guardian.user.id)} + ") + end + end + + advanced_filter(/in:unseen/) do |posts| + if @guardian.user + posts + .joins("LEFT JOIN post_timings ON + post_timings.topic_id = posts.topic_id + AND post_timings.post_number = posts.post_number + AND post_timings.user_id = #{Post.sanitize(@guardian.user.id)} + ") + .where("post_timings.user_id IS NULL") + end + end + advanced_filter(/category:(.+)/) do |posts,match| exact = false @@ -729,10 +752,10 @@ class Search if @order == :likes # likes are a pain to aggregate so skip posts_query(@limit, private_messages: opts[:private_messages]) - .select('topics.id', "post_number") + .select('topics.id', "posts.post_number") else posts_query(@limit, aggregate_search: true, private_messages: opts[:private_messages]) - .select('topics.id', "#{min_or_max}(post_number) post_number") + .select('topics.id', "#{min_or_max}(posts.post_number) post_number") .group('topics.id') end @@ -761,6 +784,7 @@ class Search post_sql = aggregate_post_sql(opts) added = 0 + aggregate_posts(post_sql[:default]).each do |p| @results.add(p) added += 1 diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index 5f1c2103375..4be4c155e7a 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -462,9 +462,49 @@ describe Search do it 'supports wiki' do topic = Fabricate(:topic) - Fabricate(:post, raw: 'this is a test 248', wiki: true, topic: topic) + topic_2 = Fabricate(:topic) + post = Fabricate(:post, raw: 'this is a test 248', wiki: true, topic: topic) + Fabricate(:post, raw: 'this is a test 248', wiki: false, topic: topic_2) - expect(Search.execute('test 248 in:wiki').posts.length).to eq(1) + expect(Search.execute('test 248').posts.length).to eq(2) + expect(Search.execute('test 248 in:wiki').posts.first).to eq(post) + end + + it 'supports searching for posts that the user has seen/unseen' do + topic = Fabricate(:topic) + topic_2 = Fabricate(:topic) + post = Fabricate(:post, raw: 'logan is longan', topic: topic) + post_2 = Fabricate(:post, raw: 'longan is logan', topic: topic_2) + + [post.user, topic.user].each do |user| + PostTiming.create!( + post_number: post.post_number, + topic: topic, + user: user, + msecs: 1 + ) + end + + expect(post.seen?(post.user)).to eq(true) + + expect(Search.execute('longan').posts.sort).to eq([post, post_2]) + + expect(Search.execute('longan in:seen', guardian: Guardian.new(post.user)).posts) + .to eq([post]) + + expect(Search.execute('longan in:seen').posts.sort).to eq([post, post_2]) + + expect(Search.execute('longan in:seen', guardian: Guardian.new(post_2.user)).posts) + .to eq([]) + + expect(Search.execute('longan', guardian: Guardian.new(post_2.user)).posts.sort) + .to eq([post, post_2]) + + expect(Search.execute('longan in:unseen', guardian: Guardian.new(post_2.user)).posts.sort) + .to eq([post, post_2]) + + expect(Search.execute('longan in:unseen', guardian: Guardian.new(post.user)).posts) + .to eq([post_2]) end it 'supports before and after, in:first, user:, @username' do