Commit 347326a2af5166256280f5151a3f07e2fc831d16

Authored by Andrew Kane
1 parent b83d8a0a

Added conversions and personalize options

README.md
... ... @@ -16,9 +16,9 @@ Plus:
16 16  
17 17 - query like SQL - no need to learn a new query language
18 18 - reindex without downtime
19   -- easily personalize results for each user [master branch]
20   -- autocomplete [master branch]
21   -- “Did you mean” suggestions [master branch]
  19 +- easily personalize results for each user
  20 +- autocomplete
  21 +- “Did you mean” suggestions
22 22  
23 23 :tangerine: Battle-tested at [Instacart](https://www.instacart.com)
24 24  
... ... @@ -132,20 +132,22 @@ To change this, use:
132 132 Product.search "fresh honey", partial: true # fresh OR honey
133 133 ```
134 134  
135   -### Autocomplete [master branch]
  135 +### Autocomplete
  136 +
  137 +![Autocomplete](http://ankane.github.io/searchkick/autocomplete.png)
136 138  
137 139 You must specify which fields use this feature since this can increase the index size significantly. Don’t worry - this gives you blazing faster queries.
138 140  
139 141 ```ruby
140   -class Product < ActiveRecord::Base
141   - searchkick autocomplete: [:name]
  142 +class Website < ActiveRecord::Base
  143 + searchkick autocomplete: ["title"]
142 144 end
143 145 ```
144 146  
145 147 Reindex and search with:
146 148  
147 149 ```ruby
148   -Product.search "puddi", autocomplete: true
  150 +Website.search "where", autocomplete: true
149 151 ```
150 152  
151 153 ### Synonyms
... ... @@ -201,10 +203,14 @@ end
201 203  
202 204 Add conversions to the index.
203 205  
  206 +**Note**: You must specify the conversions field as of version `0.2.0`.
  207 +
204 208 ```ruby
205 209 class Product < ActiveRecord::Base
206 210 has_many :searches
207 211  
  212 + searchkick conversions: "conversions" # name of field
  213 +
208 214 def search_data
209 215 {
210 216 name: name,
... ... @@ -221,14 +227,14 @@ Reindex and set up a cron job to add new conversions daily.
221 227 rake searchkick:reindex CLASS=Product
222 228 ```
223 229  
224   -### Personalized Results [master branch]
225   -
226   -**Subject to change before the next gem release**
  230 +### Personalized Results
227 231  
228   -Order results differently for each user. For example, show a user’s previously ordered products before other results.
  232 +Order results differently for each user. For example, show a user’s previously purchased products before other results.
229 233  
230 234 ```ruby
231 235 class Product < ActiveRecord::Base
  236 + searchkick personalize: "user_ids"
  237 +
232 238 def search_data
233 239 {
234 240 name: name,
... ... @@ -245,13 +251,13 @@ Reindex and search with:
245 251 Product.search "milk", user_id: 8
246 252 ```
247 253  
248   -### Suggestions [master branch]
  254 +### Suggestions
249 255  
250   -Did you mean: awesome :sunglasses:
  256 +![Suggest](http://ankane.github.io/searchkick/recursion.png)
251 257  
252 258 ```ruby
253 259 class Product < ActiveRecord::Base
254   - searchkick suggest: [:name] # fields to generate suggestions
  260 + searchkick suggest: ["name"] # fields to generate suggestions
255 261 end
256 262 ```
257 263  
... ...
lib/searchkick/model.rb
... ... @@ -3,7 +3,6 @@ module Searchkick
3 3  
4 4 def searchkick(options = {})
5 5 @searchkick_options = options.dup
6   - @searchkick_options[:conversions] = true if options[:conversions].nil?
7 6  
8 7 class_eval do
9 8 extend Searchkick::Search
... ... @@ -31,8 +30,9 @@ module Searchkick
31 30 options = self.class.instance_variable_get("@searchkick_options")
32 31  
33 32 # conversions
34   - if options[:conversions] and source["conversions"]
35   - source["conversions"] = source["conversions"].map{|k, v| {query: k, count: v} }
  33 + conversions_field = options[:conversions]
  34 + if conversions_field and source[conversions_field]
  35 + source[conversions_field] = source[conversions_field].map{|k, v| {query: k, count: v} }
36 36 end
37 37  
38 38 # hack to prevent generator field doesn't exist error
... ...
lib/searchkick/search.rb
... ... @@ -30,6 +30,9 @@ module Searchkick
30 30 offset = options[:offset] || (page && (page - 1) * per_page)
31 31 index_name = options[:index_name] || index.name
32 32  
  33 + conversions_field = @searchkick_options[:conversions]
  34 + personalize_field = @searchkick_options[:personalize]
  35 +
33 36 # TODO lose Tire DSL for more flexibility
34 37 s =
35 38 Tire::Search::Search.new do
... ... @@ -57,9 +60,9 @@ module Searchkick
57 60 end
58 61 end
59 62 end
60   - unless options[:conversions] == false
  63 + if conversions_field and options[:conversions] != false
61 64 should do
62   - nested path: "conversions", score_mode: "total" do
  65 + nested path: conversions_field, score_mode: "total" do
63 66 query do
64 67 custom_score script: "doc['count'].value" do
65 68 match "query", term
... ... @@ -76,9 +79,9 @@ module Searchkick
76 79 script "log(doc['#{options[:boost]}'].value + 2.718281828)"
77 80 end
78 81 end
79   - if options[:user_id]
  82 + if options[:user_id] and personalize_field
80 83 filter do
81   - filter :term, user_ids: options[:user_id]
  84 + filter :term, personalize_field => options[:user_id]
82 85 boost 100
83 86 end
84 87 end
... ...
test/test_helper.rb
... ... @@ -49,7 +49,9 @@ class Product &lt; ActiveRecord::Base
49 49 ["bandaid", "bandag"]
50 50 ],
51 51 autocomplete: [:name],
52   - suggest: [:name, :color]
  52 + suggest: [:name, :color],
  53 + conversions: "conversions",
  54 + personalize: "user_ids"
53 55  
54 56 attr_accessor :conversions, :user_ids
55 57  
... ...