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 +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:
|