From efacf2592151a25c3b820cb4d910bb14119af6f9 Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Sun, 22 Jun 2014 16:16:14 -0700 Subject: [PATCH] Added boost_by and boost_where options --- CHANGELOG.md | 1 + README.md | 19 ++++++++++++++----- lib/searchkick/query.rb | 35 ++++++++++++++++++++++------------- test/boost_test.rb | 21 +++++++++++++++++++++ 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa08bb4..af9396c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 0.7.8 [unreleased] +- Added `boost_by` and `boost_where` options - Added `select` option for `load: false` ## 0.7.7 diff --git a/README.md b/README.md index 4c720a9..fbc41fa 100644 --- a/README.md +++ b/README.md @@ -116,10 +116,20 @@ Limit / offset limit: 20, offset: 40 ``` -Boost by a field +### Boosting + +Boost by the value of a field + +```ruby +boost_by: [:orders_count] # give popular documents a little boost +boost_by: {orders_count: {factor: 10}} +``` + +Boost matching documents ```ruby -boost: "orders_count" # give popular documents a little boost +boost_where: {user_id: 1} +boost_where: {user_id: {value: 1, factor: 100}} ``` ### Get Everything @@ -311,22 +321,21 @@ Order results differently for each user. For example, show a user’s previousl ```ruby class Product < ActiveRecord::Base - searchkick personalize: "user_ids" def search_data { name: name, user_ids: orders.pluck(:user_id) # boost this product for these users - # [4, 8, 15, 16, 23, 42] } end + end ``` Reindex and search with: ```ruby -Product.search "milk", user_id: 8 +Product.search "milk", boost_where: {user_id: 8} ``` ### Autocomplete diff --git a/lib/searchkick/query.rb b/lib/searchkick/query.rb index 13c604c..f2fcc11 100644 --- a/lib/searchkick/query.rb +++ b/lib/searchkick/query.rb @@ -137,36 +137,45 @@ module Searchkick custom_filters = [] + boost_by = options[:boost_by] || {} + if boost_by.is_a?(Array) + boost_by = Hash[ boost_by.map{|f| [f, {factor: 1}] } ] + end if options[:boost] + boost_by[options[:boost]] = {factor: 1} + end + + boost_by.each do |field, value| custom_filters << { filter: { exists: { - field: options[:boost] + field: field } }, script_score: { - script: "log(doc['#{options[:boost]}'].value + 2.718281828)" + script: "#{value[:factor].to_f} * log(doc['#{field}'].value + 2.718281828)" } } end + boost_where = options[:boost_where] || {} if options[:user_id] and personalize_field - custom_filters << { - filter: { - term: { - personalize_field => options[:user_id] - } - }, - boost_factor: 100 - } + boost_where[personalize_field] = options[:user_id] end - if options[:personalize] + boost_where.merge!(options[:personalize]) + end + boost_where.each do |field, value| + if value.is_a?(Hash) + value, factor = value[:value], value[:factor] + else + factor = 1000 + end custom_filters << { filter: { - term: options[:personalize] + term: {field => value} }, - boost_factor: 100 + boost_factor: factor } end diff --git a/test/boost_test.rb b/test/boost_test.rb index cda2207..1eafaa5 100644 --- a/test/boost_test.rb +++ b/test/boost_test.rb @@ -67,4 +67,25 @@ class TestBoost < Minitest::Unit::TestCase assert_first "tomato", "Tomato B", personalize: {user_ids: 2} end + def test_boost_by + store [ + {name: "Tomato A"}, + {name: "Tomato B", orders_count: 10}, + {name: "Tomato C", orders_count: 100} + ] + assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_by: [:orders_count] + assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_by: {orders_count: {factor: 10}} + end + + def test_boost_where + store [ + {name: "Tomato A"}, + {name: "Tomato B", user_ids: [1, 2, 3]}, + {name: "Tomato C"}, + {name: "Tomato D"} + ] + assert_first "tomato", "Tomato B", boost_where: {user_ids: 2} + assert_first "tomato", "Tomato B", boost_where: {user_ids: {value: 2, factor: 10}} + end + end -- libgit2 0.21.0