diff --git a/lib/search.rb b/lib/search.rb index ead773d097c..e1c6509c423 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -904,13 +904,37 @@ class Search posts = categories_ignored(posts) unless @category_filter_matched posts end - - if @order == :latest || (@term.blank? && !@order) + if @order == :latest if opts[:aggregate_search] posts = posts.order("MAX(posts.created_at) DESC") else posts = posts.reorder("posts.created_at DESC") end + elsif @term.blank? && !@order + data_ranking = <<~SQL + ( + CASE categories.search_priority + WHEN #{Searchable::PRIORITIES[:very_low]} + THEN #{SiteSetting.category_search_priority_very_low_weight} + WHEN #{Searchable::PRIORITIES[:low]} + THEN #{SiteSetting.category_search_priority_low_weight} + WHEN #{Searchable::PRIORITIES[:high]} + THEN #{SiteSetting.category_search_priority_high_weight} + WHEN #{Searchable::PRIORITIES[:very_high]} + THEN #{SiteSetting.category_search_priority_very_high_weight} + ELSE + CASE WHEN topics.closed + THEN 0.9 + ELSE 1 + END + END + ) + SQL + if opts[:aggregate_search] + posts = posts.order("MAX(#{data_ranking}) DESC").order("MAX(posts.created_at) DESC") + else + posts = posts.order("#{data_ranking} DESC").order("posts.created_at DESC") + end elsif @order == :latest_topic if opts[:aggregate_search] posts = posts.order("MAX(topics.created_at) DESC") diff --git a/spec/requests/search_controller_spec.rb b/spec/requests/search_controller_spec.rb index 822ede7a0db..d1d8fff3536 100644 --- a/spec/requests/search_controller_spec.rb +++ b/spec/requests/search_controller_spec.rb @@ -219,6 +219,70 @@ describe SearchController do end end + context "search priority" do + fab!(:low_priority_category) do + Fabricate( + :category, + search_priority: Searchable::PRIORITIES[:very_low] + ) + end + fab!(:high_priority_category) do + Fabricate( + :category, + search_priority: Searchable::PRIORITIES[:high] + ) + end + fab!(:very_high_priority_category) do + Fabricate( + :category, + search_priority: Searchable::PRIORITIES[:very_high] + ) + end + fab!(:low_priority_topic) { Fabricate(:topic, category: low_priority_category) } + fab!(:high_priority_topic) { Fabricate(:topic, category: high_priority_category) } + fab!(:very_high_priority_topic) { Fabricate(:topic, category: very_high_priority_category) } + fab!(:low_priority_post) do + SearchIndexer.enable + Fabricate(:post, topic: low_priority_topic, raw: "This is a Low Priority Post") + end + fab!(:hight_priority_post) do + SearchIndexer.enable + Fabricate(:post, topic: high_priority_topic, raw: "This is a High Priority Post") + end + fab!(:old_very_hight_priority_post) do + SearchIndexer.enable + Fabricate(:old_post, topic: very_high_priority_topic, raw: "This is a Old but Very High Priority Post") + end + + it "sort posts with search priority when search term is empty" do + get "/search.json", params: { q: 'status:open' } + expect(response.status).to eq(200) + data = JSON.parse(response.body) + post1 = data["posts"].find { |e| e["id"] == old_very_hight_priority_post.id } + post2 = data["posts"].find { |e| e["id"] == low_priority_post.id } + expect(data["posts"][0]["id"]).to eq(old_very_hight_priority_post.id) + expect(post1["id"]).to be > post2["id"] + end + + it "sort posts with search priority when no order query" do + get "/search.json", params: { q: 'status:open Priority Post' } + expect(response.status).to eq(200) + data = JSON.parse(response.body) + expect(data["posts"][0]["id"]).to eq(old_very_hight_priority_post.id) + expect(data["posts"][1]["id"]).to eq(hight_priority_post.id) + expect(data["posts"][2]["id"]).to eq(low_priority_post.id) + end + + it "doesn't sort posts with search piority when query with order" do + get "/search.json", params: { q: 'status:open order:latest Priority Post' } + expect(response.status).to eq(200) + data = JSON.parse(response.body) + expect(data["posts"][0]["id"]).to eq(hight_priority_post.id) + expect(data["posts"][1]["id"]).to eq(low_priority_post.id) + expect(data["posts"][2]["id"]).to eq(old_very_hight_priority_post.id) + end + end + context "search context" do it "raises an error with an invalid context type" do get "/search/query.json", params: {