Commit 2fd44addd3ba4d72468469b7782158323a6e666f
1 parent
1ac07f94
Exists in
master
and in
18 other branches
Added boost_by_recency option
Showing
4 changed files
with
45 additions
and
3 deletions
Show diff stats
CHANGELOG.md
README.md
... | ... | @@ -201,7 +201,16 @@ boost_where: {user_id: {value: 1, factor: 100}} # default factor is 1000 |
201 | 201 | boost_where: {user_id: [{value: 1, factor: 100}, {value: 2, factor: 200}]} |
202 | 202 | ``` |
203 | 203 | |
204 | -[Conversions](#keep-getting-better) are also a great way to boost. | |
204 | +Boost by recency [master] | |
205 | + | |
206 | +```ruby | |
207 | +boost_by_recency: {created_at: {scale: "7d", decay: 0.5}} | |
208 | +``` | |
209 | + | |
210 | +You can also boost by: | |
211 | + | |
212 | +- [Conversions](#keep-getting-better) | |
213 | +- [Distance](#boost-by-distance) | |
205 | 214 | |
206 | 215 | ### Get Everything |
207 | 216 | ... | ... |
lib/searchkick/query.rb
... | ... | @@ -16,7 +16,7 @@ module Searchkick |
16 | 16 | |
17 | 17 | def initialize(klass, term = "*", **options) |
18 | 18 | unknown_keywords = options.keys - [:aggs, :body, :body_options, :boost, |
19 | - :boost_by, :boost_by_distance, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, | |
19 | + :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, | |
20 | 20 | :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load, |
21 | 21 | :match, :misspellings, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile, |
22 | 22 | :request_params, :routing, :scope_results, :select, :similar, :smart_aggs, :suggest, :track, :type, :where] |
... | ... | @@ -225,7 +225,7 @@ module Searchkick |
225 | 225 | @json = options[:body] |
226 | 226 | if @json |
227 | 227 | ignored_options = options.keys & [:aggs, :boost, |
228 | - :boost_by, :boost_by_distance, :boost_where, :conversions, :conversions_term, :exclude, :explain, | |
228 | + :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :exclude, :explain, | |
229 | 229 | :fields, :highlight, :indices_boost, :match, :misspellings, :operator, :order, |
230 | 230 | :profile, :select, :smart_aggs, :suggest, :where] |
231 | 231 | raise ArgumentError, "Options incompatible with body option: #{ignored_options.join(", ")}" if ignored_options.any? |
... | ... | @@ -407,6 +407,7 @@ module Searchkick |
407 | 407 | set_boost_by(multiply_filters, custom_filters) |
408 | 408 | set_boost_where(custom_filters) |
409 | 409 | set_boost_by_distance(custom_filters) if options[:boost_by_distance] |
410 | + set_boost_by_recency(custom_filters) if options[:boost_by_recency] | |
410 | 411 | |
411 | 412 | payload[:query] = build_query(query, filters, should, must_not, custom_filters, multiply_filters) |
412 | 413 | |
... | ... | @@ -593,6 +594,19 @@ module Searchkick |
593 | 594 | end |
594 | 595 | end |
595 | 596 | |
597 | + def set_boost_by_recency(custom_filters) | |
598 | + options[:boost_by_recency].each do |field, attributes| | |
599 | + attributes = {function: :gauss, origin: Time.now}.merge(attributes) | |
600 | + | |
601 | + custom_filters << { | |
602 | + weight: attributes[:factor] || 1, | |
603 | + attributes[:function] => { | |
604 | + field => attributes.except(:factor, :function) | |
605 | + } | |
606 | + } | |
607 | + end | |
608 | + end | |
609 | + | |
596 | 610 | def set_boost_by(multiply_filters, custom_filters) |
597 | 611 | boost_by = options[:boost_by] || {} |
598 | 612 | if boost_by.is_a?(Array) | ... | ... |
test/boost_test.rb
... | ... | @@ -149,6 +149,24 @@ class BoostTest < Minitest::Test |
149 | 149 | assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_where: {user_ids: [{value: 1, factor: 10}, {value: 3, factor: 20}]} |
150 | 150 | end |
151 | 151 | |
152 | + def test_boost_by_recency | |
153 | + store [ | |
154 | + {name: "Article 1", created_at: 2.days.ago}, | |
155 | + {name: "Article 2", created_at: 1.day.ago}, | |
156 | + {name: "Article 3", created_at: Time.now} | |
157 | + ] | |
158 | + assert_order "article", ["Article 3", "Article 2", "Article 1"], boost_by_recency: {created_at: {scale: "7d", decay: 0.5}} | |
159 | + end | |
160 | + | |
161 | + def test_boost_by_recency_origin | |
162 | + store [ | |
163 | + {name: "Article 1", created_at: 2.days.ago}, | |
164 | + {name: "Article 2", created_at: 1.day.ago}, | |
165 | + {name: "Article 3", created_at: Time.now} | |
166 | + ] | |
167 | + assert_order "article", ["Article 1", "Article 2", "Article 3"], boost_by_recency: {created_at: {origin: 2.days.ago, scale: "7d", decay: 0.5}} | |
168 | + end | |
169 | + | |
152 | 170 | def test_boost_by_distance |
153 | 171 | store [ |
154 | 172 | {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, | ... | ... |