searchkick 3.1.1 → 3.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +33 -10
- data/lib/searchkick/process_batch_job.rb +14 -1
- data/lib/searchkick/query.rb +26 -9
- data/lib/searchkick/record_data.rb +6 -1
- data/lib/searchkick/record_indexer.rb +22 -2
- data/lib/searchkick/reindex_v2_job.rb +6 -1
- data/lib/searchkick/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfa26cdc7332a0b73376d46fbd9b66cc093e919d605bbd80ceec04cfbffed914
|
4
|
+
data.tar.gz: 541e111f81bec56c621b147e5aea2b8017a91eaa3f40d074d1a5aa619da14f14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea250f38b93967d245168ab5b0cbb41a86fb0d471df8f5844e2f3e59337630b8a545df059b5fe08fb7582046749e0ffebc2b8d9152e7eee225e04ad7aedb5a54
|
7
|
+
data.tar.gz: 07f98bb46fd861dc9957ff81931965c3032dccada46e098c9723bcba68fe9365b9927c6d1283ae564aa96f83eaccdd547356de6cf3ccec7fde699a9b9d3ef18e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 3.1.2
|
2
|
+
|
3
|
+
- Improved performance of indices boost
|
4
|
+
- Fixed deletes with routing and `async` callbacks
|
5
|
+
- Fixed deletes with routing and `queue` callbacks
|
6
|
+
- Fixed deprecation warnings
|
7
|
+
- Fixed field misspellings for older partial match format
|
8
|
+
|
1
9
|
## 3.1.1
|
2
10
|
|
3
11
|
- Added per-field misspellings
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ Plus:
|
|
30
30
|
|
31
31
|
---
|
32
32
|
|
33
|
-
Does your
|
33
|
+
Does your company use Searchkick? Want free advising? Fill out [this application](https://goo.gl/forms/Or1HQTRb2rgQCNtd2)
|
34
34
|
|
35
35
|
---
|
36
36
|
|
@@ -46,10 +46,6 @@ Does your startup use Searchkick? Want a free hour of advising? Fill out [this a
|
|
46
46
|
- [Elasticsearch DSL](#advanced)
|
47
47
|
- [Reference](#reference)
|
48
48
|
|
49
|
-
**Searchkick 3.0 was recently released!** See [how to upgrade](docs/Searchkick-3-Upgrade.md)
|
50
|
-
|
51
|
-
Thinking of upgrading from Elasticsearch 5 to 6? [Read this first](#elasticsearch-5-to-6-upgrade)
|
52
|
-
|
53
49
|
## Getting Started
|
54
50
|
|
55
51
|
[Install Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/setup.html). For Homebrew, use:
|
@@ -439,6 +435,12 @@ exclude_queries = {
|
|
439
435
|
Product.search query, exclude: exclude_queries[query]
|
440
436
|
```
|
441
437
|
|
438
|
+
You can demote results by boosting by a factor less than one:
|
439
|
+
|
440
|
+
```ruby
|
441
|
+
Product.search("butter", boost_where: {category: {value: "pantry", factor: 0.5}})
|
442
|
+
```
|
443
|
+
|
442
444
|
### Emoji
|
443
445
|
|
444
446
|
Search :ice_cream::cake: and get `ice cream cake`!
|
@@ -776,9 +778,11 @@ Product.search "apples", aggs: {store_id: {limit: 10}}
|
|
776
778
|
Order
|
777
779
|
|
778
780
|
```ruby
|
779
|
-
Product.search "wingtips", aggs: {color: {order: {"
|
781
|
+
Product.search "wingtips", aggs: {color: {order: {"_key" => "asc"}}} # alphabetically
|
780
782
|
```
|
781
783
|
|
784
|
+
**Note:** Use `_term` instead of `_key` in Elasticsearch 5
|
785
|
+
|
782
786
|
[All of these options are supported](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-order)
|
783
787
|
|
784
788
|
Ranges
|
@@ -800,6 +804,8 @@ Script support
|
|
800
804
|
Product.search "*", aggs: {color: {script: {source: "'Color: ' + _value"}}}
|
801
805
|
```
|
802
806
|
|
807
|
+
**Note:** Use `inline` instead of `source` before Elasticsearch 5.6
|
808
|
+
|
803
809
|
Date histogram
|
804
810
|
|
805
811
|
```ruby
|
@@ -999,11 +1005,14 @@ Dog.search "*" # just dogs
|
|
999
1005
|
Animal.search "*", type: [Dog, Cat] # just cats and dogs
|
1000
1006
|
```
|
1001
1007
|
|
1002
|
-
**
|
1008
|
+
**Notes:**
|
1003
1009
|
|
1004
|
-
|
1005
|
-
|
1006
|
-
```
|
1010
|
+
1. The `suggest` option retrieves suggestions from the parent at the moment.
|
1011
|
+
|
1012
|
+
```ruby
|
1013
|
+
Dog.search "airbudd", suggest: true # suggestions for all animals
|
1014
|
+
```
|
1015
|
+
2. This relies on a `type` field that is automatically added to the indexed document. Be wary of defining your own `type` field in `search_data`, as it will take precedence.
|
1007
1016
|
|
1008
1017
|
## Debugging Queries
|
1009
1018
|
|
@@ -1732,6 +1741,16 @@ Create index without importing
|
|
1732
1741
|
Product.reindex(import: false)
|
1733
1742
|
```
|
1734
1743
|
|
1744
|
+
Use a different id
|
1745
|
+
|
1746
|
+
```ruby
|
1747
|
+
class Product < ApplicationRecord
|
1748
|
+
def search_document_id
|
1749
|
+
custom_id
|
1750
|
+
end
|
1751
|
+
end
|
1752
|
+
```
|
1753
|
+
|
1735
1754
|
Lazy searching
|
1736
1755
|
|
1737
1756
|
```ruby
|
@@ -1887,6 +1906,10 @@ Searchkick.index_suffix = ENV["TEST_ENV_NUMBER"]
|
|
1887
1906
|
|
1888
1907
|
Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenancy-with-searchkick/) on the [Apartment](https://github.com/influitive/apartment) gem. Follow a similar pattern if you use another gem.
|
1889
1908
|
|
1909
|
+
## Upgrading
|
1910
|
+
|
1911
|
+
See [how to upgrade to Searchkick 3](docs/Searchkick-3-Upgrade.md)
|
1912
|
+
|
1890
1913
|
## Elasticsearch 5 to 6 Upgrade
|
1891
1914
|
|
1892
1915
|
Elasticsearch 6 removes the ability to reindex with the `_all` field. Before you upgrade, we recommend disabling this field manually and specifying default fields on your models.
|
@@ -3,6 +3,10 @@ module Searchkick
|
|
3
3
|
queue_as { Searchkick.queue_name }
|
4
4
|
|
5
5
|
def perform(class_name:, record_ids:)
|
6
|
+
# separate routing from id
|
7
|
+
routing = Hash[record_ids.map { |r| r.split(/(?<!\|)\|(?!\|)/, 2).map { |v| v.gsub("||", "|") } }]
|
8
|
+
record_ids = routing.keys
|
9
|
+
|
6
10
|
klass = class_name.constantize
|
7
11
|
scope = Searchkick.load_records(klass, record_ids)
|
8
12
|
scope = scope.search_import if scope.respond_to?(:search_import)
|
@@ -10,7 +14,16 @@ module Searchkick
|
|
10
14
|
|
11
15
|
# determine which records to delete
|
12
16
|
delete_ids = record_ids - records.map { |r| r.id.to_s }
|
13
|
-
delete_records = delete_ids.map
|
17
|
+
delete_records = delete_ids.map do |id|
|
18
|
+
m = klass.new
|
19
|
+
m.id = id
|
20
|
+
if routing[id]
|
21
|
+
m.define_singleton_method(:search_routing) do
|
22
|
+
routing[id]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
m
|
26
|
+
end
|
14
27
|
|
15
28
|
# bulk reindex
|
16
29
|
index = klass.searchkick_index
|
data/lib/searchkick/query.rb
CHANGED
@@ -281,10 +281,10 @@ module Searchkick
|
|
281
281
|
prefix_length = (misspellings.is_a?(Hash) && misspellings[:prefix_length]) || 0
|
282
282
|
default_max_expansions = @misspellings_below ? 20 : 3
|
283
283
|
max_expansions = (misspellings.is_a?(Hash) && misspellings[:max_expansions]) || default_max_expansions
|
284
|
-
misspellings_fields = misspellings.is_a?(Hash) && misspellings.key?(:fields) && misspellings[:fields].map
|
284
|
+
misspellings_fields = misspellings.is_a?(Hash) && misspellings.key?(:fields) && misspellings[:fields].map(&:to_s)
|
285
285
|
|
286
286
|
if misspellings_fields
|
287
|
-
missing_fields = misspellings_fields - fields
|
287
|
+
missing_fields = misspellings_fields - fields.map { |f| base_field(f) }
|
288
288
|
if missing_fields.any?
|
289
289
|
raise ArgumentError, "All fields in per-field misspellings must also be specified in fields option"
|
290
290
|
end
|
@@ -324,7 +324,7 @@ module Searchkick
|
|
324
324
|
exclude_analyzer = nil
|
325
325
|
exclude_field = field
|
326
326
|
|
327
|
-
field_misspellings = misspellings && (!misspellings_fields || misspellings_fields.include?(field))
|
327
|
+
field_misspellings = misspellings && (!misspellings_fields || misspellings_fields.include?(base_field(field)))
|
328
328
|
|
329
329
|
if field == "_all" || field.end_with?(".analyzed")
|
330
330
|
shared_options[:cutoff_frequency] = 0.001 unless operator.to_s == "and" || field_misspellings == false
|
@@ -660,11 +660,20 @@ module Searchkick
|
|
660
660
|
def set_boost_by_indices(payload)
|
661
661
|
return unless options[:indices_boost]
|
662
662
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
663
|
+
if below52?
|
664
|
+
indices_boost = options[:indices_boost].each_with_object({}) do |(key, boost), memo|
|
665
|
+
index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key
|
666
|
+
# try to use index explicitly instead of alias: https://github.com/elasticsearch/elasticsearch/issues/4756
|
667
|
+
index_by_alias = Searchkick.client.indices.get_alias(index: index).keys.first
|
668
|
+
memo[index_by_alias || index] = boost
|
669
|
+
end
|
670
|
+
else
|
671
|
+
# array format supports alias resolution
|
672
|
+
# https://github.com/elastic/elasticsearch/pull/21393
|
673
|
+
indices_boost = options[:indices_boost].map do |key, boost|
|
674
|
+
index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key
|
675
|
+
{index => boost}
|
676
|
+
end
|
668
677
|
end
|
669
678
|
|
670
679
|
payload[:indices_boost] = indices_boost
|
@@ -812,7 +821,7 @@ module Searchkick
|
|
812
821
|
# TODO id transformation for arrays
|
813
822
|
def set_order(payload)
|
814
823
|
order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
|
815
|
-
id_field = :_uid
|
824
|
+
id_field = below60? ? :_uid : :_id
|
816
825
|
payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? id_field : k, v] }]
|
817
826
|
end
|
818
827
|
|
@@ -998,6 +1007,14 @@ module Searchkick
|
|
998
1007
|
end
|
999
1008
|
end
|
1000
1009
|
|
1010
|
+
def base_field(k)
|
1011
|
+
k.sub(/\.(analyzed|word_start|word_middle|word_end|text_start|text_middle|text_end|exact)\z/, "")
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
def below52?
|
1015
|
+
Searchkick.server_below?("5.2.0")
|
1016
|
+
end
|
1017
|
+
|
1001
1018
|
def below60?
|
1002
1019
|
Searchkick.server_below?("6.0.0")
|
1003
1020
|
end
|
@@ -34,6 +34,11 @@ module Searchkick
|
|
34
34
|
index.klass_document_type(record.class, ignore_type)
|
35
35
|
end
|
36
36
|
|
37
|
+
# memoize
|
38
|
+
def self.routing_key
|
39
|
+
@routing_key ||= Searchkick.server_below?("6.0.0") ? :_routing : :routing
|
40
|
+
end
|
41
|
+
|
37
42
|
private
|
38
43
|
|
39
44
|
def record_data
|
@@ -42,7 +47,7 @@ module Searchkick
|
|
42
47
|
_id: search_id,
|
43
48
|
_type: document_type
|
44
49
|
}
|
45
|
-
data[
|
50
|
+
data[self.class.routing_key] = record.search_routing if record.respond_to?(:search_routing)
|
46
51
|
data
|
47
52
|
end
|
48
53
|
|
@@ -20,16 +20,32 @@ module Searchkick
|
|
20
20
|
raise Searchkick::Error, "Partial reindex not supported with queue option"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
# always pass routing in case record is deleted
|
24
|
+
# before the queue job runs
|
25
|
+
if record.respond_to?(:search_routing)
|
26
|
+
routing = record.search_routing
|
27
|
+
end
|
28
|
+
|
29
|
+
# escape pipe with double pipe
|
30
|
+
value = queue_escape(record.id.to_s)
|
31
|
+
value = "#{value}|#{queue_escape(routing)}" if routing
|
32
|
+
index.reindex_queue.push(value)
|
24
33
|
when :async
|
25
34
|
unless defined?(ActiveJob)
|
26
35
|
raise Searchkick::Error, "Active Job not found"
|
27
36
|
end
|
28
37
|
|
38
|
+
# always pass routing in case record is deleted
|
39
|
+
# before the async job runs
|
40
|
+
if record.respond_to?(:search_routing)
|
41
|
+
routing = record.search_routing
|
42
|
+
end
|
43
|
+
|
29
44
|
Searchkick::ReindexV2Job.perform_later(
|
30
45
|
record.class.name,
|
31
46
|
record.id.to_s,
|
32
|
-
method_name ? method_name.to_s : nil
|
47
|
+
method_name ? method_name.to_s : nil,
|
48
|
+
routing: routing
|
33
49
|
)
|
34
50
|
else # bulk, inline/true/nil
|
35
51
|
reindex_record(method_name)
|
@@ -40,6 +56,10 @@ module Searchkick
|
|
40
56
|
|
41
57
|
private
|
42
58
|
|
59
|
+
def queue_escape(value)
|
60
|
+
value.gsub("|", "||")
|
61
|
+
end
|
62
|
+
|
43
63
|
def reindex_record(method_name)
|
44
64
|
if record.destroyed? || !record.persisted? || !record.should_index?
|
45
65
|
begin
|
@@ -9,7 +9,7 @@ module Searchkick
|
|
9
9
|
|
10
10
|
queue_as { Searchkick.queue_name }
|
11
11
|
|
12
|
-
def perform(klass, id, method_name = nil)
|
12
|
+
def perform(klass, id, method_name = nil, routing: nil)
|
13
13
|
model = klass.constantize
|
14
14
|
record =
|
15
15
|
begin
|
@@ -28,6 +28,11 @@ module Searchkick
|
|
28
28
|
unless record
|
29
29
|
record = model.new
|
30
30
|
record.id = id
|
31
|
+
if routing
|
32
|
+
record.define_singleton_method(:search_routing) do
|
33
|
+
routing
|
34
|
+
end
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
RecordIndexer.new(record).reindex(method_name, mode: :inline)
|
data/lib/searchkick/version.rb
CHANGED
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: 3.1.
|
4
|
+
version: 3.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|