searchkick 4.2.0 → 4.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -3
- data/LICENSE.txt +1 -1
- data/README.md +253 -202
- data/lib/searchkick.rb +31 -12
- data/lib/searchkick/bulk_indexer.rb +1 -1
- data/lib/searchkick/index.rb +22 -2
- data/lib/searchkick/index_options.rb +468 -382
- data/lib/searchkick/model.rb +11 -6
- data/lib/searchkick/query.rb +40 -6
- data/lib/searchkick/results.rb +10 -0
- data/lib/searchkick/version.rb +1 -1
- data/lib/tasks/searchkick.rake +12 -11
- metadata +3 -46
- data/CONTRIBUTING.md +0 -53
data/lib/searchkick/model.rb
CHANGED
@@ -5,8 +5,8 @@ module Searchkick
|
|
5
5
|
|
6
6
|
unknown_keywords = options.keys - [:_all, :_type, :batch_size, :callbacks, :case_sensitive, :conversions, :deep_paging, :default_fields,
|
7
7
|
:filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :language,
|
8
|
-
:locations, :mappings, :match, :merge_mappings, :routing, :searchable, :settings, :similarity,
|
9
|
-
:special_characters, :stem, :stem_conversions, :suggest, :synonyms, :text_end,
|
8
|
+
:locations, :mappings, :match, :merge_mappings, :routing, :searchable, :search_synonyms, :settings, :similarity,
|
9
|
+
:special_characters, :stem, :stem_conversions, :stem_exclusion, :stemmer_override, :suggest, :synonyms, :text_end,
|
10
10
|
:text_middle, :text_start, :word, :wordnet, :word_end, :word_middle, :word_start]
|
11
11
|
raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
|
12
12
|
|
@@ -41,7 +41,10 @@ module Searchkick
|
|
41
41
|
|
42
42
|
class << self
|
43
43
|
def searchkick_search(term = "*", **options, &block)
|
44
|
-
|
44
|
+
# TODO throw error in next major version
|
45
|
+
Searchkick.warn("calling search on a relation is deprecated") if Searchkick.relation?(self)
|
46
|
+
|
47
|
+
Searchkick.search(term, model: self, **options, &block)
|
45
48
|
end
|
46
49
|
alias_method Searchkick.search_method_name, :searchkick_search if Searchkick.search_method_name
|
47
50
|
|
@@ -54,10 +57,11 @@ module Searchkick
|
|
54
57
|
alias_method :search_index, :searchkick_index unless method_defined?(:search_index)
|
55
58
|
|
56
59
|
def searchkick_reindex(method_name = nil, **options)
|
57
|
-
|
60
|
+
# TODO relation = Searchkick.relation?(self)
|
61
|
+
relation = (respond_to?(:current_scope) && respond_to?(:default_scoped) && current_scope && current_scope.to_sql != default_scoped.to_sql) ||
|
58
62
|
(respond_to?(:queryable) && queryable != unscoped.with_default_scope)
|
59
63
|
|
60
|
-
searchkick_index.reindex(searchkick_klass, method_name, scoped:
|
64
|
+
searchkick_index.reindex(searchkick_klass, method_name, scoped: relation, **options)
|
61
65
|
end
|
62
66
|
alias_method :reindex, :searchkick_reindex unless method_defined?(:reindex)
|
63
67
|
|
@@ -79,8 +83,9 @@ module Searchkick
|
|
79
83
|
RecordIndexer.new(self).reindex(method_name, **options)
|
80
84
|
end unless method_defined?(:reindex)
|
81
85
|
|
86
|
+
# TODO switch to keyword arguments
|
82
87
|
def similar(options = {})
|
83
|
-
self.class.searchkick_index.similar_record(self, options)
|
88
|
+
self.class.searchkick_index.similar_record(self, **options)
|
84
89
|
end unless method_defined?(:similar)
|
85
90
|
|
86
91
|
def search_data
|
data/lib/searchkick/query.rb
CHANGED
@@ -350,7 +350,7 @@ module Searchkick
|
|
350
350
|
field_misspellings = misspellings && (!misspellings_fields || misspellings_fields.include?(base_field(field)))
|
351
351
|
|
352
352
|
if field == "_all" || field.end_with?(".analyzed")
|
353
|
-
shared_options[:cutoff_frequency] = 0.001 unless operator.to_s == "and" || field_misspellings == false
|
353
|
+
shared_options[:cutoff_frequency] = 0.001 unless operator.to_s == "and" || field_misspellings == false || (!below73? && !track_total_hits?)
|
354
354
|
qs << shared_options.merge(analyzer: "searchkick_search")
|
355
355
|
|
356
356
|
# searchkick_search and searchkick_search2 are the same for ukrainian
|
@@ -522,7 +522,7 @@ module Searchkick
|
|
522
522
|
# routing
|
523
523
|
@routing = options[:routing] if options[:routing]
|
524
524
|
|
525
|
-
if
|
525
|
+
if track_total_hits?
|
526
526
|
payload[:track_total_hits] = true
|
527
527
|
end
|
528
528
|
|
@@ -574,7 +574,8 @@ module Searchkick
|
|
574
574
|
|
575
575
|
def build_query(query, filters, should, must_not, custom_filters, multiply_filters)
|
576
576
|
if filters.any? || must_not.any? || should.any?
|
577
|
-
bool = {
|
577
|
+
bool = {}
|
578
|
+
bool[:must] = query if query
|
578
579
|
bool[:filter] = filters if filters.any? # where
|
579
580
|
bool[:must_not] = must_not if must_not.any? # exclude
|
580
581
|
bool[:should] = should if should.any? # conversions
|
@@ -871,6 +872,11 @@ module Searchkick
|
|
871
872
|
end
|
872
873
|
|
873
874
|
def where_filters(where)
|
875
|
+
# if where.respond_to?(:permitted?) && !where.permitted?
|
876
|
+
# # TODO check in more places
|
877
|
+
# Searchkick.warn("Passing unpermitted parameters will raise an exception in Searchkick 5")
|
878
|
+
# end
|
879
|
+
|
874
880
|
filters = []
|
875
881
|
(where || {}).each do |field, value|
|
876
882
|
field = :_id if field.to_s == "id"
|
@@ -953,10 +959,17 @@ module Searchkick
|
|
953
959
|
# % matches zero or more characters
|
954
960
|
# _ matches one character
|
955
961
|
# \ is escape character
|
956
|
-
|
962
|
+
# escape Lucene reserved characters
|
963
|
+
# https://www.elastic.co/guide/en/elasticsearch/reference/current/regexp-syntax.html#regexp-optional-operators
|
964
|
+
reserved = %w(. ? + * | { } [ ] ( ) " \\)
|
965
|
+
regex = op_value.dup
|
966
|
+
reserved.each do |v|
|
967
|
+
regex.gsub!(v, "\\" + v)
|
968
|
+
end
|
969
|
+
regex = regex.gsub(/(?<!\\)%/, ".*").gsub(/(?<!\\)_/, ".").gsub("\\%", "%").gsub("\\_", "_")
|
957
970
|
filters << {regexp: {field => {value: regex}}}
|
958
971
|
when :prefix
|
959
|
-
filters << {prefix: {field => op_value}}
|
972
|
+
filters << {prefix: {field => {value: op_value}}}
|
960
973
|
when :regexp # support for regexp queries without using a regexp ruby object
|
961
974
|
filters << {regexp: {field => {value: op_value}}}
|
962
975
|
when :not, :_not # not equal
|
@@ -1036,7 +1049,16 @@ module Searchkick
|
|
1036
1049
|
|
1037
1050
|
{regexp: {field => {value: source, flags: "NONE"}}}
|
1038
1051
|
else
|
1039
|
-
|
1052
|
+
# TODO add this for other values
|
1053
|
+
if value.as_json.is_a?(Enumerable)
|
1054
|
+
# query will fail, but this is better
|
1055
|
+
# same message as Active Record
|
1056
|
+
# TODO make TypeError
|
1057
|
+
# raise InvalidQueryError for backward compatibility
|
1058
|
+
raise Searchkick::InvalidQueryError, "can't cast #{value.class.name}"
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
{term: {field => {value: value}}}
|
1040
1062
|
end
|
1041
1063
|
end
|
1042
1064
|
|
@@ -1100,6 +1122,14 @@ module Searchkick
|
|
1100
1122
|
k.sub(/\.(analyzed|word_start|word_middle|word_end|text_start|text_middle|text_end|exact)\z/, "")
|
1101
1123
|
end
|
1102
1124
|
|
1125
|
+
def track_total_hits?
|
1126
|
+
(searchkick_options[:deep_paging] && !below70?) || body_options[:track_total_hits]
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
def body_options
|
1130
|
+
options[:body_options] || {}
|
1131
|
+
end
|
1132
|
+
|
1103
1133
|
def below61?
|
1104
1134
|
Searchkick.server_below?("6.1.0")
|
1105
1135
|
end
|
@@ -1108,6 +1138,10 @@ module Searchkick
|
|
1108
1138
|
Searchkick.server_below?("7.0.0")
|
1109
1139
|
end
|
1110
1140
|
|
1141
|
+
def below73?
|
1142
|
+
Searchkick.server_below?("7.3.0")
|
1143
|
+
end
|
1144
|
+
|
1111
1145
|
def below75?
|
1112
1146
|
Searchkick.server_below?("7.5.0")
|
1113
1147
|
end
|
data/lib/searchkick/results.rb
CHANGED
@@ -19,6 +19,7 @@ module Searchkick
|
|
19
19
|
@results ||= with_hit.map(&:first)
|
20
20
|
end
|
21
21
|
|
22
|
+
# TODO return enumerator like with_score
|
22
23
|
def with_hit
|
23
24
|
@with_hit ||= begin
|
24
25
|
if options[:load]
|
@@ -211,12 +212,21 @@ module Searchkick
|
|
211
212
|
end
|
212
213
|
end
|
213
214
|
|
215
|
+
# TODO return enumerator like with_score
|
214
216
|
def with_highlights(multiple: false)
|
215
217
|
with_hit.map do |result, hit|
|
216
218
|
[result, hit_highlights(hit, multiple: multiple)]
|
217
219
|
end
|
218
220
|
end
|
219
221
|
|
222
|
+
def with_score
|
223
|
+
return enum_for(:with_score) unless block_given?
|
224
|
+
|
225
|
+
with_hit.each do |result, hit|
|
226
|
+
yield result, hit["_score"]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
220
230
|
def misspellings?
|
221
231
|
@options[:misspellings]
|
222
232
|
end
|
data/lib/searchkick/version.rb
CHANGED
data/lib/tasks/searchkick.rake
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
namespace :searchkick do
|
2
|
-
desc "reindex model"
|
2
|
+
desc "reindex a model (specify CLASS)"
|
3
3
|
task reindex: :environment do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
class_name = ENV["CLASS"]
|
5
|
+
abort "USAGE: rake searchkick:reindex CLASS=Product" unless class_name
|
6
|
+
|
7
|
+
model = class_name.safe_constantize
|
8
|
+
abort "Could not find class: #{class_name}" unless model
|
9
|
+
abort "#{class_name} is not a searchkick model" unless Searchkick.models.include?(model)
|
10
|
+
|
11
|
+
puts "Reindexing #{model.name}..."
|
12
|
+
model.reindex
|
13
|
+
puts "Reindex successful"
|
14
14
|
end
|
15
15
|
|
16
16
|
namespace :reindex do
|
17
17
|
desc "reindex all models"
|
18
18
|
task all: :environment do
|
19
|
+
# eager load models to populate Searchkick.models
|
19
20
|
if Rails.respond_to?(:autoloaders) && Rails.autoloaders.zeitwerk_enabled?
|
20
21
|
# fix for https://github.com/rails/rails/issues/37006
|
21
22
|
Zeitwerk::Loader.eager_load_all
|
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: 4.
|
4
|
+
version: 4.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -52,48 +52,6 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: bundler
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rake
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
55
|
description:
|
98
56
|
email: andrew@chartkick.com
|
99
57
|
executables: []
|
@@ -101,7 +59,6 @@ extensions: []
|
|
101
59
|
extra_rdoc_files: []
|
102
60
|
files:
|
103
61
|
- CHANGELOG.md
|
104
|
-
- CONTRIBUTING.md
|
105
62
|
- LICENSE.txt
|
106
63
|
- README.md
|
107
64
|
- lib/searchkick.rb
|
@@ -145,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
102
|
- !ruby/object:Gem::Version
|
146
103
|
version: '0'
|
147
104
|
requirements: []
|
148
|
-
rubygems_version: 3.
|
105
|
+
rubygems_version: 3.1.2
|
149
106
|
signing_key:
|
150
107
|
specification_version: 4
|
151
108
|
summary: Intelligent search made easy with Rails and Elasticsearch
|
data/CONTRIBUTING.md
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
# Contributing
|
2
|
-
|
3
|
-
First, thanks for wanting to contribute. You’re awesome! :heart:
|
4
|
-
|
5
|
-
## Help
|
6
|
-
|
7
|
-
We’re not able to provide support through GitHub Issues. If you’re looking for help with your code, try posting on [Stack Overflow](https://stackoverflow.com/).
|
8
|
-
|
9
|
-
All features should be documented. If you don’t see a feature in the docs, assume it doesn’t exist.
|
10
|
-
|
11
|
-
## Bugs
|
12
|
-
|
13
|
-
Think you’ve discovered a bug?
|
14
|
-
|
15
|
-
1. Search existing issues to see if it’s been reported.
|
16
|
-
2. Try the `master` branch to make sure it hasn’t been fixed.
|
17
|
-
|
18
|
-
```rb
|
19
|
-
gem "searchkick", github: "ankane/searchkick"
|
20
|
-
```
|
21
|
-
|
22
|
-
3. Try the `debug` option when searching. This can reveal useful info.
|
23
|
-
|
24
|
-
```ruby
|
25
|
-
Product.search("something", debug: true)
|
26
|
-
```
|
27
|
-
|
28
|
-
If the above steps don’t help, create an issue.
|
29
|
-
|
30
|
-
- Recreate the problem by forking [this gist](https://gist.github.com/ankane/f80b0923d9ae2c077f41997f7b704e5c). Include a link to your gist and the output in the issue.
|
31
|
-
- For exceptions, include the complete backtrace.
|
32
|
-
|
33
|
-
## New Features
|
34
|
-
|
35
|
-
If you’d like to discuss a new feature, create an issue and start the title with `[Idea]`.
|
36
|
-
|
37
|
-
## Pull Requests
|
38
|
-
|
39
|
-
Fork the project and create a pull request. A few tips:
|
40
|
-
|
41
|
-
- Keep changes to a minimum. If you have multiple features or fixes, submit multiple pull requests.
|
42
|
-
- Follow the existing style. The code should read like it’s written by a single person.
|
43
|
-
- Add one or more tests if possible. Make sure existing tests pass with:
|
44
|
-
|
45
|
-
```sh
|
46
|
-
bundle exec rake test
|
47
|
-
```
|
48
|
-
|
49
|
-
Feel free to open an issue to get feedback on your idea before spending too much time on it.
|
50
|
-
|
51
|
-
---
|
52
|
-
|
53
|
-
This contributing guide is released under [CCO](https://creativecommons.org/publicdomain/zero/1.0/) (public domain). Use it for your own project without attribution.
|