searchkick 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: