FEATURE: Allow categories to be prioritized/deprioritized in search. (#7209)
This commit is contained in:
parent
ce75e30bf5
commit
ac661e856a
|
@ -69,7 +69,7 @@ export default buildCategoryPanel("settings", {
|
|||
});
|
||||
}
|
||||
|
||||
return options.sort((a, b) => a.value <= b.value);
|
||||
return options;
|
||||
},
|
||||
|
||||
@computed
|
||||
|
|
|
@ -2,8 +2,12 @@ module Searchable
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
PRIORITIES = Enum.new(
|
||||
ignore: 1,
|
||||
very_low: 2,
|
||||
low: 3,
|
||||
normal: 0,
|
||||
ignore: 1
|
||||
high: 4,
|
||||
very_high: 5
|
||||
)
|
||||
|
||||
included do
|
||||
|
|
|
@ -2459,6 +2459,10 @@ en:
|
|||
options:
|
||||
normal: "Normal"
|
||||
ignore: "Ignore"
|
||||
very_low: "Very Low"
|
||||
low: "Low"
|
||||
high: "High"
|
||||
very_high: "Very High"
|
||||
sort_options:
|
||||
default: "default"
|
||||
likes: "Likes"
|
||||
|
|
|
@ -1291,6 +1291,10 @@ en:
|
|||
search_query_log_max_size: "Maximum amount of search queries to keep"
|
||||
search_query_log_max_retention_days: "Maximum amount of time to keep search queries, in days."
|
||||
search_ignore_accents: "Ignore accents when searching for text."
|
||||
category_search_priority_very_low_weight: "Weight applied to ranking for very low category search priority."
|
||||
category_search_priority_low_weight: "Weight applied to ranking for low category search priority."
|
||||
category_search_priority_high_weight: "Weight applied to ranking for high category search priority."
|
||||
category_search_priority_very_high_weight: "Weight applied to ranking for very high category search priority."
|
||||
allow_uncategorized_topics: "Allow topics to be created without a category. WARNING: If there are any uncategorized topics, you must recategorize them before turning this off."
|
||||
allow_duplicate_topic_titles: "Allow topics with identical, duplicate titles."
|
||||
unique_posts_mins: "How many minutes before a user can make a post with the same content again"
|
||||
|
@ -2030,6 +2034,11 @@ en:
|
|||
max_username_length_exists: "You cannot set the maximum username length below the longest username (%{username})."
|
||||
max_username_length_range: "You cannot set the maximum below the minimum."
|
||||
invalid_hex_value: "Color values have to be 6-digit hexadecimal codes."
|
||||
category_search_priority:
|
||||
very_low_weight_invalid: "You cannot set the weight to be greater than 'category_search_priority_low_weight'."
|
||||
low_weight_invalid: "You cannot set the weight to be greater or equal to 1 or smaller than 'category_search_priority_very_low_weight'."
|
||||
high_weight_invalid: "You cannot set the weight to be greater or equal to 1 or greater than 'category_search_priority_very_high_weight'."
|
||||
very_high_weight_invalid: "You cannot set the weight to be smaller than 'category_search_priority_high_weight'."
|
||||
|
||||
placeholder:
|
||||
sso_provider_secrets:
|
||||
|
|
|
@ -1614,6 +1614,22 @@ search:
|
|||
ro: true
|
||||
sk: true
|
||||
tr_TR: true
|
||||
category_search_priority_very_low_weight:
|
||||
default: 0.6
|
||||
hidden: true
|
||||
validator: "CategorySearchPriorityWeightsValidator"
|
||||
category_search_priority_low_weight:
|
||||
default: 0.8
|
||||
hidden: true
|
||||
validator: "CategorySearchPriorityWeightsValidator"
|
||||
category_search_priority_high_weight:
|
||||
default: 1.2
|
||||
hidden: true
|
||||
validator: "CategorySearchPriorityWeightsValidator"
|
||||
category_search_priority_very_high_weight:
|
||||
default: 1.4
|
||||
hidden: true
|
||||
validator: "CategorySearchPriorityWeightsValidator"
|
||||
|
||||
uncategorized:
|
||||
version_checks:
|
||||
|
|
|
@ -836,9 +836,27 @@ class Search
|
|||
posts = posts.order("posts.like_count DESC")
|
||||
end
|
||||
else
|
||||
# 0|32 default normalization scaled into the range zero to one
|
||||
data_ranking = <<~SQL
|
||||
TS_RANK_CD(
|
||||
post_search_data.search_data, #{ts_query(weight_filter: weights)}
|
||||
(
|
||||
TS_RANK_CD(
|
||||
post_search_data.search_data,
|
||||
#{ts_query(weight_filter: weights)},
|
||||
0|32
|
||||
) *
|
||||
(
|
||||
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 1
|
||||
END
|
||||
)
|
||||
)
|
||||
SQL
|
||||
|
||||
|
|
|
@ -103,7 +103,9 @@ class SiteSettings::TypeSupervisor
|
|||
|
||||
opts[:validator] = opts[:validator].try(:constantize)
|
||||
if (validator_type = (opts[:validator] || validator_for(@types[name])))
|
||||
@validators[name] = { class: validator_type, opts: opts.slice(*VALIDATOR_OPTS) }
|
||||
validator_opts = opts.slice(*VALIDATOR_OPTS)
|
||||
validator_opts[:name] = name
|
||||
@validators[name] = { class: validator_type, opts: validator_opts }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
class CategorySearchPriorityWeightsValidator
|
||||
def initialize(opts = {})
|
||||
@name = opts[:name].to_s
|
||||
end
|
||||
|
||||
def valid_value?(val)
|
||||
val = val.to_f
|
||||
|
||||
case @name
|
||||
when "category_search_priority_very_low_weight"
|
||||
val < SiteSetting.category_search_priority_low_weight
|
||||
when "category_search_priority_low_weight"
|
||||
val < 1 && val > SiteSetting.category_search_priority_very_low_weight
|
||||
when "category_search_priority_high_weight"
|
||||
val > 1 && val < SiteSetting.category_search_priority_very_high_weight
|
||||
when "category_search_priority_very_high_weight"
|
||||
val > SiteSetting.category_search_priority_high_weight
|
||||
end
|
||||
end
|
||||
|
||||
def error_message
|
||||
key = @name[/category_search_priority_(\w+)_weight/, 1]
|
||||
I18n.t("site_settings.errors.category_search_priority.#{key}_weight_invalid")
|
||||
end
|
||||
end
|
|
@ -486,6 +486,26 @@ describe Search do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'categories with different priorities' do
|
||||
let(:category2) { Fabricate(:category) }
|
||||
|
||||
it "should return posts in the right order" do
|
||||
raw = "The pure genuine evian"
|
||||
post = Fabricate(:post, topic: category.topic, raw: raw)
|
||||
post2 = Fabricate(:post, topic: category2.topic, raw: raw)
|
||||
|
||||
search = Search.execute(raw)
|
||||
|
||||
expect(search.posts).to eq([post2, post])
|
||||
|
||||
category.update!(search_priority: Searchable::PRIORITIES[:high])
|
||||
|
||||
search = Search.execute(raw)
|
||||
|
||||
expect(search.posts).to eq([post, post2])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'groups' do
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
require 'rails_helper'
|
||||
require 'validators/category_search_priority_weights_validator'
|
||||
|
||||
RSpec.describe CategorySearchPriorityWeightsValidator do
|
||||
it "should validate the results correctly" do
|
||||
expect do
|
||||
SiteSetting.category_search_priority_very_low_weight = 0.9
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
|
||||
[1, 0].each do |value|
|
||||
expect do
|
||||
SiteSetting.category_search_priority_low_weight = value
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
['0.2', 10].each do |value|
|
||||
expect do
|
||||
SiteSetting.category_search_priority_high_weight = value
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
expect do
|
||||
SiteSetting.category_search_priority_very_high_weight = 1.1
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue