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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +53 -6
- data/lib/searchkick.rb +4 -0
- data/lib/searchkick/model.rb +2 -3
- data/lib/searchkick/query.rb +30 -3
- data/lib/searchkick/reindex.rb +2 -2
- data/lib/searchkick/results.rb +17 -11
- data/lib/searchkick/version.rb +1 -1
- data/test/boost_test.rb +9 -0
- data/test/highlight_test.rb +12 -0
- metadata +2 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3c68977ac74916a49b5e7dd8c22cb18dd5793dc
|
4
|
+
data.tar.gz: 3a03323a99f0ee6b726796aad8b2242a9606dfe0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4618c81555aa422098d15533378efbc13cfb5070685649a8d3410e65a63628eaed3f0f60783b8cbe2972e3c98d6604c1fefc3cf6c6dba663fada4f7e8a215499
|
7
|
+
data.tar.gz: 789ff34e062fa62c06f7fa6b1fed9c9f95ba64c99d35ceb58553d473bfc9a16b29f0b3f8ff56688822be9cf90a862d9b0d9633c3a1ef7f657186829693a4c84b
|
data/CHANGELOG.md
CHANGED
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 [
|
734
|
+
For the best performance, add [Typhoeus](https://github.com/typhoeus/typhoeus) to your Gemfile.
|
707
735
|
|
708
736
|
```ruby
|
709
|
-
gem '
|
737
|
+
gem 'typhoeus'
|
710
738
|
```
|
711
739
|
|
712
|
-
|
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:**
|
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
data/lib/searchkick/model.rb
CHANGED
@@ -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, :
|
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,
|
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
|
data/lib/searchkick/query.rb
CHANGED
@@ -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
|
-
|
324
|
-
|
325
|
-
|
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
|
|
data/lib/searchkick/reindex.rb
CHANGED
@@ -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
|
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
|
206
|
+
if Searchkick.env == "test"
|
207
207
|
settings.merge!(number_of_shards: 1, number_of_replicas: 0)
|
208
208
|
end
|
209
209
|
|
data/lib/searchkick/results.rb
CHANGED
@@ -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
|
data/lib/searchkick/version.rb
CHANGED
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
|
data/test/highlight_test.rb
CHANGED
@@ -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.
|
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-
|
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:
|