diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dd7cd0..fdda7b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.0.3 [unreleased] - Added support for pagination with `body` option +- Added `boost_by_recency` option - Fixed "Model Search Data" output for `debug` option - Fixed `reindex_status` error - Fixed error with optional operators in Ruby regexp diff --git a/README.md b/README.md index 70612a7..04b1497 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,16 @@ boost_where: {user_id: {value: 1, factor: 100}} # default factor is 1000 boost_where: {user_id: [{value: 1, factor: 100}, {value: 2, factor: 200}]} ``` -[Conversions](#keep-getting-better) are also a great way to boost. +Boost by recency [master] + +```ruby +boost_by_recency: {created_at: {scale: "7d", decay: 0.5}} +``` + +You can also boost by: + +- [Conversions](#keep-getting-better) +- [Distance](#boost-by-distance) ### Get Everything diff --git a/lib/searchkick/query.rb b/lib/searchkick/query.rb index feefeca..8cc6e52 100644 --- a/lib/searchkick/query.rb +++ b/lib/searchkick/query.rb @@ -16,7 +16,7 @@ module Searchkick def initialize(klass, term = "*", **options) unknown_keywords = options.keys - [:aggs, :body, :body_options, :boost, - :boost_by, :boost_by_distance, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, + :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load, :match, :misspellings, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile, :request_params, :routing, :scope_results, :select, :similar, :smart_aggs, :suggest, :track, :type, :where] @@ -225,7 +225,7 @@ module Searchkick @json = options[:body] if @json ignored_options = options.keys & [:aggs, :boost, - :boost_by, :boost_by_distance, :boost_where, :conversions, :conversions_term, :exclude, :explain, + :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :exclude, :explain, :fields, :highlight, :indices_boost, :match, :misspellings, :operator, :order, :profile, :select, :smart_aggs, :suggest, :where] raise ArgumentError, "Options incompatible with body option: #{ignored_options.join(", ")}" if ignored_options.any? @@ -407,6 +407,7 @@ module Searchkick set_boost_by(multiply_filters, custom_filters) set_boost_where(custom_filters) set_boost_by_distance(custom_filters) if options[:boost_by_distance] + set_boost_by_recency(custom_filters) if options[:boost_by_recency] payload[:query] = build_query(query, filters, should, must_not, custom_filters, multiply_filters) @@ -593,6 +594,19 @@ module Searchkick end end + def set_boost_by_recency(custom_filters) + options[:boost_by_recency].each do |field, attributes| + attributes = {function: :gauss, origin: Time.now}.merge(attributes) + + custom_filters << { + weight: attributes[:factor] || 1, + attributes[:function] => { + field => attributes.except(:factor, :function) + } + } + end + end + def set_boost_by(multiply_filters, custom_filters) boost_by = options[:boost_by] || {} if boost_by.is_a?(Array) diff --git a/test/boost_test.rb b/test/boost_test.rb index f34f634..5194260 100644 --- a/test/boost_test.rb +++ b/test/boost_test.rb @@ -149,6 +149,24 @@ class BoostTest < Minitest::Test assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_where: {user_ids: [{value: 1, factor: 10}, {value: 3, factor: 20}]} end + def test_boost_by_recency + store [ + {name: "Article 1", created_at: 2.days.ago}, + {name: "Article 2", created_at: 1.day.ago}, + {name: "Article 3", created_at: Time.now} + ] + assert_order "article", ["Article 3", "Article 2", "Article 1"], boost_by_recency: {created_at: {scale: "7d", decay: 0.5}} + end + + def test_boost_by_recency_origin + store [ + {name: "Article 1", created_at: 2.days.ago}, + {name: "Article 2", created_at: 1.day.ago}, + {name: "Article 3", created_at: Time.now} + ] + assert_order "article", ["Article 1", "Article 2", "Article 3"], boost_by_recency: {created_at: {origin: 2.days.ago, scale: "7d", decay: 0.5}} + end + def test_boost_by_distance store [ {name: "San Francisco", latitude: 37.7833, longitude: -122.4167}, -- libgit2 0.21.0