Skip to content

Commit

Permalink
FEATURE: Allow categories to be prioritized/deprioritized in search. (d…
Browse files Browse the repository at this point in the history
  • Loading branch information
tgxworld authored Mar 25, 2019
1 parent ce75e30 commit ac661e8
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default buildCategoryPanel("settings", {
});
}

return options.sort((a, b) => a.value <= b.value);
return options;
},

@computed
Expand Down
6 changes: 5 additions & 1 deletion app/models/concerns/searchable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
9 changes: 9 additions & 0 deletions config/locales/server.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down
16 changes: 16 additions & 0 deletions config/site_settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 20 additions & 2 deletions lib/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -836,9 +836,27 @@ def posts_query(limit, opts = nil)
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

Expand Down
4 changes: 3 additions & 1 deletion lib/site_settings/type_supervisor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ def load_setting(name_arg, opts = {})

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

Expand Down
25 changes: 25 additions & 0 deletions lib/validators/category_search_priority_weights_validator.rb
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions spec/components/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,26 @@ def result(current_user)
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
Expand Down
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit ac661e8

Please sign in to comment.