UX: Exclude search ignored and user muted categories in similarity search (#19349)

When finding the candidates for `Topic.similar_to`, we will now ignore
topics in categories where `Category#search_priority` has been set to
ignore and also topics in categories which the user has specifically
muted.

Internal Ref: /t/87132
This commit is contained in:
Alan Guo Xiang Tan 2022-12-07 11:33:01 +08:00 committed by GitHub
parent 5aaaf26636
commit 207b764ea3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 4 deletions

View File

@ -634,14 +634,27 @@ class Topic < ActiveRecord::Base
tsquery = Search.to_tsquery(term: tsquery, joiner: "|")
guardian = Guardian.new(user)
excluded_category_ids_sql = Category.secured(guardian).where(search_priority: Searchable::PRIORITIES[:ignore]).select(:id).to_sql
if user
excluded_category_ids_sql = <<~SQL
#{excluded_category_ids_sql}
UNION
#{CategoryUser.where(notification_level: CategoryUser.notification_levels[:muted], user: user).select(:category_id).to_sql}
SQL
end
candidates = Topic
.visible
.listable_topics
.secured(Guardian.new(user))
.secured(guardian)
.joins("JOIN topic_search_data s ON topics.id = s.topic_id")
.joins("LEFT JOIN categories c ON topics.id = c.topic_id")
.where("search_data @@ #{tsquery}")
.where("c.topic_id IS NULL")
.where("topics.category_id NOT IN (#{excluded_category_ids_sql})")
.order("ts_rank(search_data, #{tsquery}) DESC")
.limit(SiteSetting.max_similar_results * 3)

View File

@ -685,10 +685,28 @@ RSpec.describe Topic do
expect(topics).to eq([])
end
it 'does not return topics from categories with search priority set to ignore' do
expect(Topic.similar_to("has evil trout made any topics?", "")).to eq([topic])
topic.category.update!(search_priority: Searchable::PRIORITIES[:ignore])
expect(Topic.similar_to("has evil trout made any topics?", "")).to eq([])
end
it 'does not return topics from categories which the user has muted' do
expect(Topic.similar_to("has evil trout made any topics?", "", user)).to eq([topic])
CategoryUser.create!(category: topic.category, user: user, notification_level: CategoryUser.notification_levels[:muted])
expect(Topic.similar_to("has evil trout made any topics?", "", user)).to eq([])
end
context "with secure categories" do
fab!(:group) { Fabricate(:group) }
fab!(:private_category) { Fabricate(:private_category, group: group) }
before do
category.update!(read_restricted: true)
topic.update!(category: category)
topic.update!(category: private_category)
end
it "doesn't return topics from private categories" do
@ -696,7 +714,8 @@ RSpec.describe Topic do
end
it "should return the cat since the user can see it" do
Guardian.any_instance.expects(:secure_category_ids).returns([category.id])
group.add(user)
expect(Topic.similar_to("has evil trout made any topics?", "i am wondering has evil trout made any topics?", user)).to include(topic)
end
end