searchkick 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b8b951d29bd106ae56b6ca7d2738574430f76ae
4
- data.tar.gz: a56ba366f77bfb6f0378e8f5711704bec31ef2cf
3
+ metadata.gz: a3c68977ac74916a49b5e7dd8c22cb18dd5793dc
4
+ data.tar.gz: 3a03323a99f0ee6b726796aad8b2242a9606dfe0
5
5
  SHA512:
6
- metadata.gz: 7f532ecc2e7bb89ad4a705400c89151d7b5ab114efc7c8d4fa9771578de22a3e3ed5361863b6cea9cf56ea9ab6cf4b3379899168af619242844035197c1b294a
7
- data.tar.gz: 37c8d654358714fc2a5389190940fdf5f9714b60ded559364ec28ea6a639ed69570f80495e004e2d17c3354e8aada69b7f5e9cf062176f595d4e626024921b1c
6
+ metadata.gz: 4618c81555aa422098d15533378efbc13cfb5070685649a8d3410e65a63628eaed3f0f60783b8cbe2972e3c98d6604c1fefc3cf6c6dba663fada4f7e8a215499
7
+ data.tar.gz: 789ff34e062fa62c06f7fa6b1fed9c9f95ba64c99d35ceb58553d473bfc9a16b29f0b3f8ff56688822be9cf90a862d9b0d9633c3a1ef7f657186829693a4c84b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.8.4
2
+
3
+ - Added `boost_by_distance`
4
+ - More flexible highlight options
5
+ - Better `env` logic
6
+
1
7
  ## 0.8.3
2
8
 
3
9
  - Added support for ActiveJob
data/README.md CHANGED
@@ -124,7 +124,7 @@ Boost important fields
124
124
  fields: ["title^10", "description"]
125
125
  ```
126
126
 
127
- Boost by the value of a field
127
+ Boost by the value of a field (field must be numeric)
128
128
 
129
129
  ```ruby
130
130
  boost_by: [:orders_count] # give popular documents a little boost
@@ -553,7 +553,7 @@ Highlight the search query in the results.
553
553
  bands = Band.search "cinema", fields: [:name], highlight: true
554
554
  ```
555
555
 
556
- **Note:** The `fields` option is required.
556
+ **Note:** The `fields` option is required, unless highlight options are given - see below.
557
557
 
558
558
  View the highlighted fields with:
559
559
 
@@ -569,6 +569,20 @@ To change the tag, use:
569
569
  Band.search "cinema", fields: [:name], highlight: {tag: "<strong>"}
570
570
  ```
571
571
 
572
+ To highlight and search different fields, use:
573
+
574
+ ```ruby
575
+ Band.search "cinema", fields: [:name], highlight: {fields: [:description]}
576
+ ```
577
+
578
+ Additional options, including fragment size, can be specified for each field:
579
+
580
+ ```ruby
581
+ Band.search "cinema", fields: [:name], highlight: {fields: {name: {fragment_size: 200}}}
582
+ ```
583
+
584
+ You can find available highlight options in the [Elasticsearch reference](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html#_highlighted_fragments).
585
+
572
586
  ### Similar Items
573
587
 
574
588
  Find similar items.
@@ -602,6 +616,20 @@ Bounded by a box
602
616
  City.search "san", where: {location: {top_left: [38, -123], bottom_right: [37, -122]}}
603
617
  ```
604
618
 
619
+ ### Boost By Distance
620
+
621
+ Boost results by distance - closer results are boosted more
622
+
623
+ ```ruby
624
+ City.search "san", boost_by_distance: {field: :location, origin: [37, -122]}
625
+ ```
626
+
627
+ Also supports [additional options](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_decay_functions)
628
+
629
+ ```ruby
630
+ City.search "san", boost_by_distance: {field: :location, origin: [37, -122], function: :linear, scale: "30mi", decay: 0.5}
631
+ ```
632
+
605
633
  ## Inheritance
606
634
 
607
635
  Searchkick supports single table inheritance.
@@ -703,15 +731,20 @@ rake searchkick:reindex CLASS=Product
703
731
 
704
732
  ### Performance
705
733
 
706
- For the best performance, add [Patron](https://github.com/toland/patron) to your Gemfile.
734
+ For the best performance, add [Typhoeus](https://github.com/typhoeus/typhoeus) to your Gemfile.
707
735
 
708
736
  ```ruby
709
- gem 'patron'
737
+ gem 'typhoeus'
710
738
  ```
711
739
 
712
- Searchkick will automatically use it.
740
+ And create an initializer with:
741
+
742
+ ```ruby
743
+ require "typhoeus/adapters/faraday"
744
+ Ethon.logger = Logger.new("/dev/null")
745
+ ```
713
746
 
714
- **Note:** Patron is not available for Windows.
747
+ **Note:** Typhoeus is not available for Windows.
715
748
 
716
749
  ### Automatic Failover
717
750
 
@@ -723,6 +756,20 @@ Searchkick.client = Elasticsearch::Client.new(hosts: ["localhost:9200", "localho
723
756
 
724
757
  See [elasticsearch-transport](https://github.com/elasticsearch/elasticsearch-ruby/blob/master/elasticsearch-transport) for a complete list of options.
725
758
 
759
+ ### Lograge
760
+
761
+ Add the following to `config/environments/production.rb`:
762
+
763
+ ```ruby
764
+ config.lograge.custom_options = lambda do |event|
765
+ options = {}
766
+ options[:search] = event.payload[:searchkick_runtime] if event.payload[:searchkick_runtime].to_f > 0
767
+ options
768
+ end
769
+ ```
770
+
771
+ See [Production Rails](https://github.com/ankane/production_rails) for other good practices.
772
+
726
773
  ## Advanced
727
774
 
728
775
  Prefer to use the [Elasticsearch DSL](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html) but still want awesome features like zero-downtime reindexing?
data/lib/searchkick.rb CHANGED
@@ -63,6 +63,10 @@ module Searchkick
63
63
  def self.callbacks?
64
64
  callbacks
65
65
  end
66
+
67
+ def self.env
68
+ @env ||= ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
69
+ end
66
70
  end
67
71
 
68
72
  # TODO find better ActiveModel hook
@@ -5,15 +5,14 @@ module Searchkick
5
5
  raise "Only call searchkick once per model" if respond_to?(:searchkick_index)
6
6
 
7
7
  class_eval do
8
- cattr_reader :searchkick_options, :searchkick_env, :searchkick_klass
8
+ cattr_reader :searchkick_options, :searchkick_klass
9
9
 
10
10
  callbacks = options.has_key?(:callbacks) ? options[:callbacks] : true
11
11
 
12
12
  class_variable_set :@@searchkick_options, options.dup
13
- class_variable_set :@@searchkick_env, ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
14
13
  class_variable_set :@@searchkick_klass, self
15
14
  class_variable_set :@@searchkick_callbacks, callbacks
16
- class_variable_set :@@searchkick_index, options[:index_name] || [options[:index_prefix], model_name.plural, searchkick_env].compact.join("_")
15
+ class_variable_set :@@searchkick_index, options[:index_name] || [options[:index_prefix], model_name.plural, Searchkick.env].compact.join("_")
17
16
 
18
17
  def self.searchkick_index
19
18
  index = class_variable_get :@@searchkick_index
@@ -209,6 +209,21 @@ module Searchkick
209
209
  }
210
210
  end
211
211
 
212
+ boost_by_distance = options[:boost_by_distance]
213
+ if boost_by_distance
214
+ boost_by_distance = {function: :gauss, scale: "5mi"}.merge(boost_by_distance)
215
+ if !boost_by_distance[:field] or !boost_by_distance[:origin]
216
+ raise ArgumentError, "boost_by_distance requires :field and :origin"
217
+ end
218
+ function_params = boost_by_distance.select{|k,v| [:origin, :scale, :offset, :decay].include?(k) }
219
+ function_params[:origin] = function_params[:origin].reverse
220
+ custom_filters << {
221
+ boost_by_distance[:function] => {
222
+ boost_by_distance[:field] => function_params
223
+ }
224
+ }
225
+ end
226
+
212
227
  if custom_filters.any?
213
228
  payload = {
214
229
  function_score: {
@@ -320,9 +335,21 @@ module Searchkick
320
335
  payload[:highlight] = {
321
336
  fields: Hash[ fields.map{|f| [f, {}] } ]
322
337
  }
323
- if options[:highlight].is_a?(Hash) and tag = options[:highlight][:tag]
324
- payload[:highlight][:pre_tags] = [tag]
325
- payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")]
338
+
339
+ if options[:highlight].is_a?(Hash)
340
+ if tag = options[:highlight][:tag]
341
+ payload[:highlight][:pre_tags] = [tag]
342
+ payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")]
343
+ end
344
+
345
+ highlight_fields = options[:highlight][:fields]
346
+ if highlight_fields
347
+ payload[:highlight][:fields] = {}
348
+
349
+ highlight_fields.each do |name, opts|
350
+ payload[:highlight][:fields]["#{name}.analyzed"] = opts || {}
351
+ end
352
+ end
326
353
  end
327
354
  end
328
355
 
@@ -7,7 +7,7 @@ module Searchkick
7
7
  skip_import = options[:import] == false
8
8
 
9
9
  alias_name = searchkick_index.name
10
- new_name = alias_name + "_" + Time.now.strftime("%Y%m%d%H%M%S%L")
10
+ new_name = "#{alias_name}_#{Time.now.strftime('%Y%m%d%H%M%S%L')}"
11
11
  index = Searchkick::Index.new(new_name)
12
12
 
13
13
  clean_indices
@@ -203,7 +203,7 @@ module Searchkick
203
203
  }
204
204
  }
205
205
 
206
- if searchkick_env == "test"
206
+ if Searchkick.env == "test"
207
207
  settings.merge!(number_of_shards: 1, number_of_replicas: 0)
208
208
  end
209
209
 
@@ -26,17 +26,7 @@ module Searchkick
26
26
  if options[:includes]
27
27
  records = records.includes(options[:includes])
28
28
  end
29
- results[type] =
30
- if records.respond_to?(:primary_key) and records.primary_key
31
- # ActiveRecord
32
- records.where(records.primary_key => grouped_hits.map{|hit| hit["_id"] }).to_a
33
- elsif records.respond_to?(:all) and records.all.respond_to?(:for_ids)
34
- # Mongoid 2
35
- records.all.for_ids(grouped_hits.map{|hit| hit["_id"] }).to_a
36
- else
37
- # Mongoid 3+
38
- records.queryable.for_ids(grouped_hits.map{|hit| hit["_id"] }).to_a
39
- end
29
+ results[type] = results_query(records, grouped_hits)
40
30
  end
41
31
 
42
32
  # sort
@@ -143,5 +133,21 @@ module Searchkick
143
133
  @response["hits"]["hits"]
144
134
  end
145
135
 
136
+ private
137
+
138
+ def results_query(records, grouped_hits)
139
+ if records.respond_to?(:primary_key) and records.primary_key
140
+ # ActiveRecord
141
+ records.where(records.primary_key => grouped_hits.map{|hit| hit["_id"] }).to_a
142
+ elsif records.respond_to?(:all) and records.all.respond_to?(:for_ids)
143
+ # Mongoid 2
144
+ records.all.for_ids(grouped_hits.map{|hit| hit["_id"] }).to_a
145
+ elsif records.respond_to?(:queryable)
146
+ # Mongoid 3+
147
+ records.queryable.for_ids(grouped_hits.map{|hit| hit["_id"] }).to_a
148
+ else
149
+ raise "Not sure how to load records"
150
+ end
151
+ end
146
152
  end
147
153
  end
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "0.8.3"
2
+ VERSION = "0.8.4"
3
3
  end
data/test/boost_test.rb CHANGED
@@ -104,4 +104,13 @@ class TestBoost < Minitest::Test
104
104
  assert_first "tomato", "Tomato B", boost_where: {user_ids: {value: 2, factor: 10}}
105
105
  end
106
106
 
107
+ def test_boost_by_distance
108
+ store [
109
+ {name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
110
+ {name: "San Antonio", latitude: 29.4167, longitude: -98.5000},
111
+ {name: "San Marino", latitude: 43.9333, longitude: 12.4667}
112
+ ]
113
+ assert_order "san", ["San Francisco", "San Antonio", "San Marino"], boost_by_distance: {field: :location, origin: [37, -122], scale: "1000mi"}
114
+ end
115
+
107
116
  end
@@ -19,6 +19,18 @@ class TestHighlight < Minitest::Test
19
19
  assert_equal "<em>Cinema</em> Orange", highlight[:color]
20
20
  end
21
21
 
22
+ def test_fields
23
+ store [{name: "Two Door Cinema Club", color: "Cinema Orange"}]
24
+ highlight = Product.search("cinema", fields: [:name, :color], highlight: {fields: [:name]}).with_details.first[1][:highlight]
25
+ assert_equal "Two Door <em>Cinema</em> Club", highlight[:name]
26
+ assert_equal nil, highlight[:color]
27
+ end
28
+
29
+ def test_field_options
30
+ store_names ["Two Door Cinema Club are a Northern Irish indie rock band"]
31
+ assert_equal "Two Door <em>Cinema</em> Club are", Product.search("cinema", fields: [:name], highlight: {fields: {name: {fragment_size: 20}}}).with_details.first[1][:highlight][:name]
32
+ end
33
+
22
34
  def test_multiple_words
23
35
  store_names ["Hello World Hello"]
24
36
  assert_equal "<em>Hello</em> World <em>Hello</em>", Product.search("hello", fields: [:name], highlight: true).with_details.first[1][:highlight][:name]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-21 00:00:00.000000000 Z
11
+ date: 2014-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -188,4 +188,3 @@ test_files:
188
188
  - test/suggest_test.rb
189
189
  - test/synonyms_test.rb
190
190
  - test/test_helper.rb
191
- has_rdoc: