searchkick 4.4.1 → 4.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff49d45a4473f44b07e8f1654d47e9b0590fd71eb3c6567f62b2fbcdc1e837b9
4
- data.tar.gz: fd6ac4c931c7250787bc6f905c6c72b8412355e6b505bb2ef9d8cf5731d2939d
3
+ metadata.gz: 782d732ce3dca45ba3654f3afa2ee565fc396543179dbdc87a0ee7418a151a3c
4
+ data.tar.gz: 2752fb40094f068a97e77009634fccf7a1433182294835ad077a66632d43bcb6
5
5
  SHA512:
6
- metadata.gz: 05630a20b302fd406e5545935861b6616db79e2dd12e2eb11fe82bb3733c8b21af1087b7ad8d0fd4bd93eb3a07d2bd67461815a293746a2d2c2d3f2148d7147b
7
- data.tar.gz: 571528f3967fd921e92dda6413313d29bd9048ee832e44bdb1a31a297178c3ee2f0b31dead3c573b297da96b676fdd74467bd7aa514c6a97f2a38b2500901057
6
+ metadata.gz: b1125b09caaf20b0dcc8aa7c55755e257338499dda6d09427e139f9167d9e5b2e9971657b830352babe8100c510236412fbaa5a6edf9617c8eefcbe7aff4d2c7
7
+ data.tar.gz: b111187e5e1d05f19120f850833a491405727811fde6b31465f6021dffdd01b44e55c6e9a19b930246a4a92671ddda62aa65f9fa6fb6793342a5581009961985
@@ -1,3 +1,8 @@
1
+ ## 4.4.2 (2020-11-23)
2
+
3
+ - Added `missing_records` method to results
4
+ - Fixed issue with `like` and special characters
5
+
1
6
  ## 4.4.1 (2020-06-24)
2
7
 
3
8
  - Added `stem_exclusion` and `stemmer_override` options
data/README.md CHANGED
@@ -22,11 +22,11 @@ Plus:
22
22
  - supports many languages
23
23
  - works with ActiveRecord, Mongoid, and NoBrainer
24
24
 
25
- :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
25
+ Check out [Searchjoy](https://github.com/ankane/searchjoy) for analytics and [Autosuggest](https://github.com/ankane/autosuggest) for query suggestions
26
26
 
27
- :speech_balloon: Get [handcrafted updates](https://chartkick.us7.list-manage.com/subscribe?u=952c861f99eb43084e0a49f98&id=6ea6541e8e&group[0][4]=true) for new features
27
+ :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
28
28
 
29
- [![Build Status](https://travis-ci.org/ankane/searchkick.svg?branch=master)](https://travis-ci.org/ankane/searchkick)
29
+ [![Build Status](https://github.com/ankane/searchkick/workflows/build/badge.svg?branch=master)](https://github.com/ankane/searchkick/actions)
30
30
 
31
31
  ## Contents
32
32
 
@@ -1202,6 +1202,14 @@ end
1202
1202
  FactoryBot.create(:product, :some_trait, :reindex, some_attribute: "foo")
1203
1203
  ```
1204
1204
 
1205
+ ### GitHub Actions
1206
+
1207
+ Check out [setup-elasticsearch](https://github.com/ankane/setup-elasticsearch) for an easy way to install Elasticsearch.
1208
+
1209
+ ```yml
1210
+ - uses: ankane/setup-elasticsearch@v1
1211
+ ```
1212
+
1205
1213
  ## Deployment
1206
1214
 
1207
1215
  Searchkick uses `ENV["ELASTICSEARCH_URL"]` for the Elasticsearch server. This defaults to `http://localhost:9200`.
@@ -967,7 +967,7 @@ module Searchkick
967
967
  regex.gsub!(v, "\\" + v)
968
968
  end
969
969
  regex = regex.gsub(/(?<!\\)%/, ".*").gsub(/(?<!\\)_/, ".").gsub("\\%", "%").gsub("\\_", "_")
970
- filters << {regexp: {field => {value: regex}}}
970
+ filters << {regexp: {field => {value: regex, flags: "NONE"}}}
971
971
  when :prefix
972
972
  filters << {prefix: {field => {value: op_value}}}
973
973
  when :regexp # support for regexp queries without using a regexp ruby object
@@ -22,76 +22,17 @@ module Searchkick
22
22
  # TODO return enumerator like with_score
23
23
  def with_hit
24
24
  @with_hit ||= begin
25
- if options[:load]
26
- # results can have different types
27
- results = {}
28
-
29
- hits.group_by { |hit, _| hit["_index"] }.each do |index, grouped_hits|
30
- klasses =
31
- if @klass
32
- [@klass]
33
- else
34
- index_alias = index.split("_")[0..-2].join("_")
35
- Array((options[:index_mapping] || {})[index_alias])
36
- end
37
- raise Searchkick::Error, "Unknown model for index: #{index}" unless klasses.any?
38
-
39
- results[index] = {}
40
- klasses.each do |klass|
41
- results[index].merge!(results_query(klass, grouped_hits).to_a.index_by { |r| r.id.to_s })
42
- end
43
- end
44
-
45
- missing_ids = []
46
-
47
- # sort
48
- results =
49
- hits.map do |hit|
50
- result = results[hit["_index"]][hit["_id"].to_s]
51
- if result && !(options[:load].is_a?(Hash) && options[:load][:dumpable])
52
- if (hit["highlight"] || options[:highlight]) && !result.respond_to?(:search_highlights)
53
- highlights = hit_highlights(hit)
54
- result.define_singleton_method(:search_highlights) do
55
- highlights
56
- end
57
- end
58
- end
59
- [result, hit]
60
- end.select do |result, hit|
61
- missing_ids << hit["_id"] unless result
62
- result
63
- end
64
-
65
- if missing_ids.any?
66
- Searchkick.warn("Records in search index do not exist in database: #{missing_ids.join(", ")}")
67
- end
68
-
69
- results
70
- else
71
- hits.map do |hit|
72
- result =
73
- if hit["_source"]
74
- hit.except("_source").merge(hit["_source"])
75
- elsif hit["fields"]
76
- hit.except("fields").merge(hit["fields"])
77
- else
78
- hit
79
- end
80
-
81
- if hit["highlight"] || options[:highlight]
82
- highlight = Hash[hit["highlight"].to_a.map { |k, v| [base_field(k), v.first] }]
83
- options[:highlighted_fields].map { |k| base_field(k) }.each do |k|
84
- result["highlighted_#{k}"] ||= (highlight[k] || result[k])
85
- end
86
- end
87
-
88
- result["id"] ||= result["_id"] # needed for legacy reasons
89
- [HashWrapper.new(result), hit]
90
- end
25
+ if missing_records.any?
26
+ Searchkick.warn("Records in search index do not exist in database: #{missing_records.map { |v| v[:id] }.join(", ")}")
91
27
  end
28
+ with_hit_and_missing_records[0]
92
29
  end
93
30
  end
94
31
 
32
+ def missing_records
33
+ @missing_records ||= with_hit_and_missing_records[1]
34
+ end
35
+
95
36
  def suggestions
96
37
  if response["suggest"]
97
38
  response["suggest"].values.flat_map { |v| v.first["options"] }.sort_by { |o| -o["score"] }.map { |o| o["text"] }.uniq
@@ -278,6 +219,90 @@ module Searchkick
278
219
 
279
220
  private
280
221
 
222
+ def with_hit_and_missing_records
223
+ @with_hit_and_missing_records ||= begin
224
+ missing_records = []
225
+
226
+ if options[:load]
227
+ grouped_hits = hits.group_by { |hit, _| hit["_index"] }
228
+
229
+ # determine models
230
+ index_models = {}
231
+ grouped_hits.each do |index, _|
232
+ models =
233
+ if @klass
234
+ [@klass]
235
+ else
236
+ index_alias = index.split("_")[0..-2].join("_")
237
+ Array((options[:index_mapping] || {})[index_alias])
238
+ end
239
+ raise Searchkick::Error, "Unknown model for index: #{index}" unless models.any?
240
+ index_models[index] = models
241
+ end
242
+
243
+ # fetch results
244
+ results = {}
245
+ grouped_hits.each do |index, index_hits|
246
+ results[index] = {}
247
+ index_models[index].each do |model|
248
+ results[index].merge!(results_query(model, index_hits).to_a.index_by { |r| r.id.to_s })
249
+ end
250
+ end
251
+
252
+ # sort
253
+ results =
254
+ hits.map do |hit|
255
+ result = results[hit["_index"]][hit["_id"].to_s]
256
+ if result && !(options[:load].is_a?(Hash) && options[:load][:dumpable])
257
+ if (hit["highlight"] || options[:highlight]) && !result.respond_to?(:search_highlights)
258
+ highlights = hit_highlights(hit)
259
+ result.define_singleton_method(:search_highlights) do
260
+ highlights
261
+ end
262
+ end
263
+ end
264
+ [result, hit]
265
+ end.select do |result, hit|
266
+ unless result
267
+ models = index_models[hit["_index"]]
268
+ missing_records << {
269
+ id: hit["_id"],
270
+ # may be multiple models for inheritance with child models
271
+ # not ideal to return different types
272
+ # but this situation shouldn't be common
273
+ model: models.size == 1 ? models.first : models
274
+ }
275
+ end
276
+ result
277
+ end
278
+ else
279
+ results =
280
+ hits.map do |hit|
281
+ result =
282
+ if hit["_source"]
283
+ hit.except("_source").merge(hit["_source"])
284
+ elsif hit["fields"]
285
+ hit.except("fields").merge(hit["fields"])
286
+ else
287
+ hit
288
+ end
289
+
290
+ if hit["highlight"] || options[:highlight]
291
+ highlight = Hash[hit["highlight"].to_a.map { |k, v| [base_field(k), v.first] }]
292
+ options[:highlighted_fields].map { |k| base_field(k) }.each do |k|
293
+ result["highlighted_#{k}"] ||= (highlight[k] || result[k])
294
+ end
295
+ end
296
+
297
+ result["id"] ||= result["_id"] # needed for legacy reasons
298
+ [HashWrapper.new(result), hit]
299
+ end
300
+ end
301
+
302
+ [results, missing_records]
303
+ end
304
+ end
305
+
281
306
  def results_query(records, hits)
282
307
  ids = hits.map { |hit| hit["_id"] }
283
308
  if options[:includes] || options[:model_includes]
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "4.4.1"
2
+ VERSION = "4.4.2"
3
3
  end
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.1
4
+ version: 4.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-25 00:00:00.000000000 Z
11
+ date: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description:
55
+ description:
56
56
  email: andrew@chartkick.com
57
57
  executables: []
58
58
  extensions: []
@@ -87,7 +87,7 @@ homepage: https://github.com/ankane/searchkick
87
87
  licenses:
88
88
  - MIT
89
89
  metadata: {}
90
- post_install_message:
90
+ post_install_message:
91
91
  rdoc_options: []
92
92
  require_paths:
93
93
  - lib
@@ -102,8 +102,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  requirements: []
105
- rubygems_version: 3.1.2
106
- signing_key:
105
+ rubygems_version: 3.1.4
106
+ signing_key:
107
107
  specification_version: 4
108
108
  summary: Intelligent search made easy with Rails and Elasticsearch
109
109
  test_files: []