Commit 182c82e949c9f4c463ee19ecbcc6085d6890673c

Authored by Andrew Kane
1 parent efacf259

Added ability to boost fields

CHANGELOG.md
1 1 ## 0.7.8 [unreleased]
2 2  
3 3 - Added `boost_by` and `boost_where` options
  4 +- Added ability to boost fields - `name^10`
4 5 - Added `select` option for `load: false`
5 6  
6 7 ## 0.7.7
... ...
README.md
... ... @@ -118,6 +118,12 @@ limit: 20, offset: 40
118 118  
119 119 ### Boosting
120 120  
  121 +Boost important fields
  122 +
  123 +```ruby
  124 +fields: ["title^10", "description"]
  125 +```
  126 +
121 127 Boost by the value of a field
122 128  
123 129 ```ruby
... ... @@ -192,6 +198,12 @@ Available options are:
192 198 :text_end
193 199 ```
194 200  
  201 +To boost fields, use:
  202 +
  203 +```ruby
  204 +fields: [{"name^2" => :word_start}] # better interface on the way
  205 +```
  206 +
195 207 ### Language
196 208  
197 209 Searchkick defaults to English for stemming. To change this, use:
... ...
lib/searchkick/query.rb
... ... @@ -15,6 +15,7 @@ module Searchkick
15 15 @term = term
16 16 @options = options
17 17  
  18 + boost_fields = {}
18 19 fields =
19 20 if options[:fields]
20 21 if options[:autocomplete]
... ... @@ -22,7 +23,10 @@ module Searchkick
22 23 else
23 24 options[:fields].map do |value|
24 25 k, v = value.is_a?(Hash) ? value.to_a.first : [value, :word]
25   - "#{k}.#{v == :word ? "analyzed" : v}"
  26 + k2, boost = k.split("^", 2)
  27 + field = "#{k2}.#{v == :word ? "analyzed" : v}"
  28 + boost_fields[field] = boost.to_i if boost
  29 + field
26 30 end
27 31 end
28 32 else
... ... @@ -74,17 +78,19 @@ module Searchkick
74 78 else
75 79 queries = []
76 80 fields.each do |field|
  81 + factor = boost_fields[field] || 1
77 82 shared_options = {
78 83 fields: [field],
79 84 query: term,
80 85 use_dis_max: false,
81   - operator: operator
  86 + operator: operator,
  87 + boost: factor
82 88 }
83 89 if field == "_all" or field.end_with?(".analyzed")
84 90 shared_options[:cutoff_frequency] = 0.001 unless operator == "and"
85 91 queries.concat [
86   - {multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search")},
87   - {multi_match: shared_options.merge(boost: 10, analyzer: "searchkick_search2")}
  92 + {multi_match: shared_options.merge(boost: 10 * factor, analyzer: "searchkick_search")},
  93 + {multi_match: shared_options.merge(boost: 10 * factor, analyzer: "searchkick_search2")}
88 94 ]
89 95 if options[:misspellings] != false
90 96 distance = (options[:misspellings].is_a?(Hash) && options[:misspellings][:distance]) || 1
... ...
test/boost_test.rb
... ... @@ -67,6 +67,22 @@ class TestBoost < Minitest::Unit::TestCase
67 67 assert_first "tomato", "Tomato B", personalize: {user_ids: 2}
68 68 end
69 69  
  70 + def test_boost_fields
  71 + store [
  72 + {name: "Red", color: "White"},
  73 + {name: "White", color: "Red Red Red"}
  74 + ]
  75 + assert_order "red", ["Red", "White"], fields: ["name^10", "color"]
  76 + end
  77 +
  78 + def test_boost_fields_word_start
  79 + store [
  80 + {name: "Red", color: "White"},
  81 + {name: "White", color: "Red Red Red"}
  82 + ]
  83 + assert_order "red", ["Red", "White"], fields: [{"name^10" => :word_start}, "color"]
  84 + end
  85 +
70 86 def test_boost_by
71 87 store [
72 88 {name: "Tomato A"},
... ...