searchkick 3.1.1 → 3.1.2
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 +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
|