Commit 2fd44addd3ba4d72468469b7782158323a6e666f

Authored by Andrew
1 parent 1ac07f94

Added boost_by_recency option

CHANGELOG.md
1 1 ## 3.0.3 [unreleased]
2 2  
3 3 - Added support for pagination with `body` option
  4 +- Added `boost_by_recency` option
4 5 - Fixed "Model Search Data" output for `debug` option
5 6 - Fixed `reindex_status` error
6 7 - Fixed error with optional operators in Ruby regexp
... ...
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 &lt; 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},
... ...