chewy 8.0.1 → 8.2.0
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 +48 -0
- data/README.md +2 -16
- data/lib/chewy/errors.rb +3 -0
- data/lib/chewy/fields/root.rb +3 -3
- data/lib/chewy/index/actions.rb +13 -11
- data/lib/chewy/index/adapter/object.rb +17 -0
- data/lib/chewy/index/adapter/orm.rb +20 -0
- data/lib/chewy/index/crutch.rb +12 -2
- data/lib/chewy/index/import/bulk_builder.rb +8 -5
- data/lib/chewy/index/import/progressbar.rb +79 -0
- data/lib/chewy/index/import/routine.rb +3 -2
- data/lib/chewy/index/import.rb +73 -19
- data/lib/chewy/index/witchcraft.rb +5 -4
- data/lib/chewy/multi_search.rb +1 -1
- data/lib/chewy/rake_helper.rb +19 -2
- data/lib/chewy/search/parameters/runtime_mappings.rb +14 -0
- data/lib/chewy/search/request.rb +18 -2
- data/lib/chewy/search/scrolling.rb +14 -6
- data/lib/chewy/stash.rb +10 -6
- data/lib/chewy/strategy/delayed_sidekiq/worker.rb +1 -1
- data/lib/chewy/version.rb +1 -1
- data/lib/chewy.rb +1 -0
- metadata +5 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4797e925ff275cb6b742ef6dd7be3a03d6033f73c93453305d08383c11252c00
|
|
4
|
+
data.tar.gz: 46b165cfeda3df1558221bc668a7749b1c98ec8a937e4956f710dfbe93934cb1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6451084c18ae23ee908f0ba6c00cffa2cc5abcec29ecc4c911f7e8340081f4b0b89c66d91f2c9dda988c412bcd5a995705ff219d00147c4d52209749f375ff84
|
|
7
|
+
data.tar.gz: b2dd7dda7bae223e450165ff35be42ea814b57d8f06cd0546970a0aed3bed113f290ccc233724248a0cdce3af7b9ef8ac60d2e0e155b1dc6f19376375ccb1990
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## master (unreleased)
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
### Changes
|
|
10
|
+
|
|
11
|
+
## 8.2.0 (2026-05-29)
|
|
12
|
+
|
|
13
|
+
### New Features
|
|
14
|
+
|
|
15
|
+
* Add `progressbar:` option to `import`/`import!` and a `PROGRESS=1` rake env toggle for `chewy:reset` / `chewy:update`. The bar is opt-in (default `false`), supports a `:unbounded` spinner mode that skips the `import_count` query, and is safe in parallel mode — workers stay process-based, the bar is incremented in the parent via `Parallel`'s `finish:` callback. Reintroduces the feature originally added in [#787](https://github.com/toptal/chewy/pull/787) and reverted in [#800](https://github.com/toptal/chewy/pull/800) without the GVL regression.
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* Fix race condition during `reset!` where the unsuffixed concrete index could be recreated by a concurrent process between the delete and the alias creation, causing the alias creation to fail with an index/alias name collision.
|
|
20
|
+
The delete + alias-add are now performed in a single atomic `_aliases` cluster state update via the `remove_index` action.
|
|
21
|
+
No public API or layout change.
|
|
22
|
+
* [#992](https://github.com/toptal/chewy/issues/992): `import(update_fields: [])` is now a no-op (zero fields to update) instead of triggering a full document reindex. The default of `update_fields` is now `nil` (still performs a full reindex). Behavior change: any caller passing an explicit empty array previously got a silent full reimport; they will now skip the update.
|
|
23
|
+
|
|
24
|
+
### Changes
|
|
25
|
+
|
|
26
|
+
* [#1024](https://github.com/toptal/chewy/pull/1024): Replace deprecated `ZRANGEBYSCORE` with `ZRANGE ... BYSCORE` in the `delayed_sidekiq` worker Lua script. `ZRANGEBYSCORE` has been deprecated in Redis since 6.2.0.
|
|
27
|
+
|
|
28
|
+
## 8.1.0 (2026-05-28)
|
|
29
|
+
|
|
30
|
+
### New Features
|
|
31
|
+
|
|
32
|
+
* [#887](https://github.com/toptal/chewy/pull/887): Add support [runtime_mappings](https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-search-request.html). ([@TakuyaKurimoto](https://github.com/TakuyaKurimoto))
|
|
33
|
+
* [#996](https://github.com/toptal/chewy/pull/996): Add `context:` option to `import`/`import!` for passing custom data to crutch blocks and field value procs without redundant DB queries.
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* [#878](https://github.com/toptal/chewy/issues/878): Flatten `Chewy::Stash::Journal.for` to use a single `terms` filter instead of a chain of `bool.should` clauses. Fixes Elasticsearch `indices.query.bool.max_nested_depth` errors when applying or cleaning the journal across many indices.
|
|
38
|
+
|
|
39
|
+
### Changes
|
|
40
|
+
|
|
41
|
+
* [#916](https://github.com/toptal/chewy/pull/916): Raise error in #scroll_batches when search backend returns a failure. ([@tomdev][])
|
|
42
|
+
* [#1008](https://github.com/toptal/chewy/pull/1008): Promote Elasticsearch to a native GitHub Actions service with a health-check gate, replacing the fragile `docker compose` + `sleep 15` approach. ([@mattmenefee][])
|
|
43
|
+
* [#1010](https://github.com/toptal/chewy/pull/1010): Add Chewy 7/ES 7 to Chewy 8/ES 8 migration guide and fix stale `Elasticsearch::Transport` namespace references in docs. ([@mattmenefee][])
|
|
44
|
+
* [#1011](https://github.com/toptal/chewy/pull/1011): Replace deprecated `Sidekiq::Testing` API with new `Sidekiq 8.1+` testing API and silence Sidekiq logger during spec runs. ([@mattmenefee][], [@mjankowski][])
|
|
45
|
+
* [#1013](https://github.com/toptal/chewy/pull/1013): Fix `drop_indices` test helper to use `format: 'json'` for ES version portability. If you define a custom `drop_indices` helper in your test suite, update it to use `Chewy.client.cat.indices(format: 'json')` instead of parsing the text-format response. ([@mattmenefee][])
|
|
46
|
+
* [#1014](https://github.com/toptal/chewy/pull/1014): Improve contributing documentation with development setup instructions, PR workflow, and grammar fixes. ([@mattmenefee][])
|
|
47
|
+
|
|
3
48
|
## 8.0.1 (2026-03-12)
|
|
4
49
|
|
|
5
50
|
### New Features
|
|
@@ -874,10 +919,12 @@
|
|
|
874
919
|
[@marshall]: https://github.com/marshall
|
|
875
920
|
[@matchbookmac]: https://github.com/matchbookmac
|
|
876
921
|
[@matthee]: https://github.com/matthee
|
|
922
|
+
[@mattmenefee]: https://github.com/mattmenefee
|
|
877
923
|
[@mattzollinhofer]: https://github.com/mattzollinhofer
|
|
878
924
|
[@menglewis]: https://github.com/menglewis
|
|
879
925
|
[@mikeyhogarth]: https://github.com/mikeyhogarth
|
|
880
926
|
[@milk1000cc]: https://github.com/milk1000cc
|
|
927
|
+
[@mjankowski]: https://github.com/mjankowski
|
|
881
928
|
[@mkcode]: https://github.com/mkcode
|
|
882
929
|
[@mpeychich]: https://github.com/mpeychich
|
|
883
930
|
[@mrbrdo]: https://github.com/mrbrdo
|
|
@@ -901,6 +948,7 @@
|
|
|
901
948
|
[@socialchorus]: https://github.com/socialchorus
|
|
902
949
|
[@taylor-au]: https://github.com/taylor-au
|
|
903
950
|
[@TikiTDO]: https://github.com/TikiTDO
|
|
951
|
+
[@tomdev]: https://github.com/tomdev
|
|
904
952
|
[@undr]: https://github.com/undr
|
|
905
953
|
[@Vitalina-Vakulchyk]: https://github.com/Vitalina-Vakulchyk
|
|
906
954
|
[@webgago]: https://github.com/webgago
|
data/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
[](http://badge.fury.io/rb/chewy)
|
|
2
2
|
[](https://github.com/toptal/chewy/actions/workflows/ruby.yml)
|
|
3
|
-
[](https://codeclimate.com/github/toptal/chewy)
|
|
4
|
-
[](http://inch-ci.org/github/toptal/chewy)
|
|
5
3
|
|
|
6
4
|
# Chewy
|
|
7
5
|
|
|
@@ -47,7 +45,7 @@ Chewy aims to support all Ruby and Rails versions that are currently maintained
|
|
|
47
45
|
|
|
48
46
|
### Ruby
|
|
49
47
|
|
|
50
|
-
Chewy is compatible with MRI 3.2-
|
|
48
|
+
Chewy is compatible with MRI 3.2-4.0.
|
|
51
49
|
|
|
52
50
|
### Elasticsearch compatibility matrix
|
|
53
51
|
|
|
@@ -274,19 +272,7 @@ Use the standard client settings with your Cloud credentials (API key or user/pa
|
|
|
274
272
|
|
|
275
273
|
## Contributing
|
|
276
274
|
|
|
277
|
-
|
|
278
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
279
|
-
3. Implement your changes, cover it with specs and make sure old specs are passing
|
|
280
|
-
4. Commit your changes (`git commit -am 'Add some feature'`)
|
|
281
|
-
5. Push to the branch (`git push origin my-new-feature`)
|
|
282
|
-
6. Create new Pull Request
|
|
283
|
-
|
|
284
|
-
Use the following Rake tasks to control the Elasticsearch cluster while developing, if you prefer native Elasticsearch installation over the dockerized one:
|
|
285
|
-
|
|
286
|
-
```bash
|
|
287
|
-
rake elasticsearch:start # start Elasticsearch cluster on 9250 port for tests
|
|
288
|
-
rake elasticsearch:stop # stop Elasticsearch
|
|
289
|
-
```
|
|
275
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup instructions, how to run tests, and the pull request workflow.
|
|
290
276
|
|
|
291
277
|
## Copyright
|
|
292
278
|
|
data/lib/chewy/errors.rb
CHANGED
data/lib/chewy/fields/root.rb
CHANGED
|
@@ -61,8 +61,8 @@ module Chewy
|
|
|
61
61
|
# @param fields [Array<Symbol>] a list of fields to compose, every field will be composed if empty
|
|
62
62
|
# @return [Hash] JSON-ready hash with stringified keys
|
|
63
63
|
#
|
|
64
|
-
def compose(object, crutches = nil, fields: [])
|
|
65
|
-
result = evaluate([object, crutches])
|
|
64
|
+
def compose(object, crutches = nil, fields: [], context: {})
|
|
65
|
+
result = evaluate([object, crutches, context])
|
|
66
66
|
|
|
67
67
|
if children.present?
|
|
68
68
|
child_fields = if fields.present?
|
|
@@ -72,7 +72,7 @@ module Chewy
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
child_fields.each_with_object({}) do |field, memo|
|
|
75
|
-
memo.merge!(field.compose(result, crutches) || {})
|
|
75
|
+
memo.merge!(field.compose(result, crutches, context) || {})
|
|
76
76
|
end.as_json
|
|
77
77
|
elsif fields.present?
|
|
78
78
|
result.as_json(only: fields, root: false)
|
data/lib/chewy/index/actions.rb
CHANGED
|
@@ -7,12 +7,13 @@ module Chewy
|
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
9
9
|
module ClassMethods
|
|
10
|
-
# Checks index existance. Returns true or false
|
|
10
|
+
# Checks index existance. Supports suffixes. Returns true or false
|
|
11
11
|
#
|
|
12
12
|
# UsersIndex.exists? #=> true
|
|
13
|
+
# UsersIndex.exists?('11-2024') #=> false
|
|
13
14
|
#
|
|
14
|
-
def exists?
|
|
15
|
-
client.indices.exists(index: index_name)
|
|
15
|
+
def exists?(suffix = nil)
|
|
16
|
+
client.indices.exists(index: index_name(suffix: suffix))
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
# Creates index and applies mappings and settings.
|
|
@@ -163,16 +164,17 @@ module Chewy
|
|
|
163
164
|
))
|
|
164
165
|
original_index_settings suffixed_name
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
actions = indexes.map { |index| {remove: {index: index, alias: general_name}} }
|
|
168
|
+
actions << {add: {index: suffixed_name, alias: general_name}}
|
|
169
|
+
if indexes.blank? && exists?
|
|
170
|
+
index_names = client.indices.get_alias(index: general_name).keys
|
|
171
|
+
actions << {remove_index: {index: index_names.join(',')}}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
client.indices.update_aliases body: {actions: actions}
|
|
173
175
|
client.indices.delete index: indexes if indexes.present?
|
|
174
176
|
|
|
175
|
-
self.journal.apply(start_time, **import_options) if apply_journal
|
|
177
|
+
self.journal.apply(start_time, **import_options.except(:progressbar)) if apply_journal
|
|
176
178
|
result
|
|
177
179
|
else
|
|
178
180
|
purge!
|
|
@@ -146,6 +146,23 @@ module Chewy
|
|
|
146
146
|
collection.each_slice(options[:batch_size], &block)
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
+
# Returns the count of objects that would be imported. Used by the
|
|
150
|
+
# progressbar feature to set the total. Mirrors {#import_args} input
|
|
151
|
+
# handling but does not enumerate batches.
|
|
152
|
+
#
|
|
153
|
+
# @return [Integer]
|
|
154
|
+
def import_count(*args)
|
|
155
|
+
args = args.dup
|
|
156
|
+
args.extract_options!
|
|
157
|
+
collection = if args.empty? && @target.respond_to?(import_all_method)
|
|
158
|
+
@target.send(import_all_method)
|
|
159
|
+
else
|
|
160
|
+
args.flatten(1).compact
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
collection.count
|
|
164
|
+
end
|
|
165
|
+
|
|
149
166
|
# This method is used internally by the request DSL when the
|
|
150
167
|
# collection of ORM/ODM objects is requested.
|
|
151
168
|
#
|
|
@@ -96,6 +96,26 @@ module Chewy
|
|
|
96
96
|
end
|
|
97
97
|
alias_method :import_references, :import_fields
|
|
98
98
|
|
|
99
|
+
# Returns the count of records that would be imported. Used by the
|
|
100
|
+
# progressbar feature to set the total. Accepts the same shapes as
|
|
101
|
+
# {#import}: nothing (uses default scope), a relation, or an array
|
|
102
|
+
# of ids/objects.
|
|
103
|
+
#
|
|
104
|
+
# @return [Integer]
|
|
105
|
+
def import_count(*args)
|
|
106
|
+
args = args.dup
|
|
107
|
+
args.extract_options!
|
|
108
|
+
collection = if args.empty?
|
|
109
|
+
default_scope
|
|
110
|
+
elsif args.first.is_a?(relation_class)
|
|
111
|
+
args.first
|
|
112
|
+
else
|
|
113
|
+
args.flatten.compact
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
collection.count
|
|
117
|
+
end
|
|
118
|
+
|
|
99
119
|
def load(ids, **options)
|
|
100
120
|
scope = all_scope_where_ids_in(ids)
|
|
101
121
|
additional_scope = options[options[:_index].to_sym].try(:[], :scope) || options[:scope]
|
data/lib/chewy/index/crutch.rb
CHANGED
|
@@ -9,9 +9,12 @@ module Chewy
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
class Crutches
|
|
12
|
-
|
|
12
|
+
attr_reader :context
|
|
13
|
+
|
|
14
|
+
def initialize(index, collection, context = {})
|
|
13
15
|
@index = index
|
|
14
16
|
@collection = collection
|
|
17
|
+
@context = context
|
|
15
18
|
@crutches_instances = {}
|
|
16
19
|
end
|
|
17
20
|
|
|
@@ -26,7 +29,14 @@ module Chewy
|
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
def [](name)
|
|
29
|
-
@crutches_instances[name] ||=
|
|
32
|
+
@crutches_instances[name] ||= begin
|
|
33
|
+
block = @index._crutches[:"#{name}"]
|
|
34
|
+
if block.arity > 1 || block.arity < -1
|
|
35
|
+
block.call(@collection, @context)
|
|
36
|
+
else
|
|
37
|
+
block.call(@collection)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
30
40
|
end
|
|
31
41
|
end
|
|
32
42
|
|
|
@@ -13,11 +13,12 @@ module Chewy
|
|
|
13
13
|
# @param to_index [Array<Object>] objects to index
|
|
14
14
|
# @param delete [Array<Object>] objects or ids to delete
|
|
15
15
|
# @param fields [Array<Symbol, String>] and array of fields for documents update
|
|
16
|
-
def initialize(index, to_index: [], delete: [], fields:
|
|
16
|
+
def initialize(index, to_index: [], delete: [], fields: nil, context: {})
|
|
17
17
|
@index = index
|
|
18
18
|
@to_index = to_index
|
|
19
19
|
@delete = delete
|
|
20
|
-
@fields = fields
|
|
20
|
+
@fields = fields&.map(&:to_sym)
|
|
21
|
+
@context = context
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
# Returns ES API-ready bulk requiest body.
|
|
@@ -42,10 +43,12 @@ module Chewy
|
|
|
42
43
|
private
|
|
43
44
|
|
|
44
45
|
def crutches_for_index
|
|
45
|
-
@crutches_for_index ||= Chewy::Index::Crutch::Crutches.new @index, @to_index
|
|
46
|
+
@crutches_for_index ||= Chewy::Index::Crutch::Crutches.new @index, @to_index, @context
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def index_entry(object)
|
|
50
|
+
return [] if @fields&.empty?
|
|
51
|
+
|
|
49
52
|
entry = {}
|
|
50
53
|
entry[:_id] = index_object_ids[object] if index_object_ids[object]
|
|
51
54
|
entry[:routing] = routing(object) if join_field?
|
|
@@ -257,13 +260,13 @@ module Chewy
|
|
|
257
260
|
end
|
|
258
261
|
|
|
259
262
|
def data_for(object, fields: [], crutches: crutches_for_index)
|
|
260
|
-
@index.compose(object, crutches, fields: fields)
|
|
263
|
+
@index.compose(object, crutches, fields: fields, context: @context)
|
|
261
264
|
end
|
|
262
265
|
|
|
263
266
|
def parent_changed?(data, old_parent)
|
|
264
267
|
return false unless old_parent
|
|
265
268
|
return false unless join_field?
|
|
266
|
-
return false unless @fields
|
|
269
|
+
return false unless @fields&.include?(join_field.to_sym)
|
|
267
270
|
return false unless data.key?(join_field)
|
|
268
271
|
|
|
269
272
|
# The join field value can be a hash, e.g.:
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Chewy
|
|
2
|
+
class Index
|
|
3
|
+
module Import
|
|
4
|
+
# Thin wrapper around `ruby-progressbar` for import feedback.
|
|
5
|
+
#
|
|
6
|
+
# Unlike the original PR #787 implementation, this wrapper is only
|
|
7
|
+
# touched from the parent process: serial imports increment it directly,
|
|
8
|
+
# and parallel imports increment it via `Parallel`'s `finish:` callback
|
|
9
|
+
# (which runs in the parent under an internal mutex). The workers stay
|
|
10
|
+
# process-based, so there is no GVL contention as in PR #787 / #800.
|
|
11
|
+
#
|
|
12
|
+
# `Progressbar.build` returns a NULL object when the feature is disabled,
|
|
13
|
+
# so call sites do not need feature guards.
|
|
14
|
+
class Progressbar
|
|
15
|
+
NULL = Object.new
|
|
16
|
+
class << NULL
|
|
17
|
+
def increment(_); end
|
|
18
|
+
def total=(_); end
|
|
19
|
+
def finish; end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
BOUNDED_FORMAT = '%t |%B| %p%% %c/%C %e'.freeze
|
|
23
|
+
UNBOUNDED_FORMAT = '%t %c (%a)'.freeze
|
|
24
|
+
TITLE = 'Importing'.freeze
|
|
25
|
+
|
|
26
|
+
# @param enabled [Boolean, :unbounded] feature flag. `:unbounded` shows
|
|
27
|
+
# a spinner with no total (skip `import_count`).
|
|
28
|
+
# @param total [Integer, nil] expected total; ignored when `:unbounded`.
|
|
29
|
+
# @return [Progressbar, NULL]
|
|
30
|
+
def self.build(enabled, total)
|
|
31
|
+
return NULL unless enabled
|
|
32
|
+
|
|
33
|
+
unless '::ProgressBar'.safe_constantize
|
|
34
|
+
raise 'The `ruby-progressbar` gem is required for import progress, ' \
|
|
35
|
+
"please add `gem 'ruby-progressbar'` to your Gemfile"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return new if enabled == :unbounded
|
|
39
|
+
|
|
40
|
+
new(normalize_total(total))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Some ActiveRecord scopes (e.g., `.group(...)`) make `.count` return a
|
|
44
|
+
# Hash rather than an Integer. Coerce so we still get a usable total.
|
|
45
|
+
def self.normalize_total(total)
|
|
46
|
+
case total
|
|
47
|
+
when Hash then total.values.sum
|
|
48
|
+
when Integer then total
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
attr_reader :bar
|
|
53
|
+
|
|
54
|
+
def initialize(total = nil)
|
|
55
|
+
format = total ? BOUNDED_FORMAT : UNBOUNDED_FORMAT
|
|
56
|
+
@bar = ::ProgressBar.create(title: TITLE, total: total, format: format)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Clamps to total when bounded — action_objects may include :delete
|
|
60
|
+
# entries (parent-child re-indexing, delete_if scope) that aren't
|
|
61
|
+
# counted by `adapter.import_count`, which would otherwise raise
|
|
62
|
+
# ProgressBar::InvalidProgressError.
|
|
63
|
+
def increment(by)
|
|
64
|
+
target = bar.progress + by
|
|
65
|
+
target = [bar.total, target].min if bar.total
|
|
66
|
+
bar.progress = target
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def total=(value)
|
|
70
|
+
bar.total = value
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def finish
|
|
74
|
+
bar.finish unless bar.finished?
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -31,7 +31,7 @@ module Chewy
|
|
|
31
31
|
|
|
32
32
|
DEFAULT_OPTIONS = {
|
|
33
33
|
refresh: true,
|
|
34
|
-
update_fields:
|
|
34
|
+
update_fields: nil,
|
|
35
35
|
update_failover: true,
|
|
36
36
|
batch_size: Chewy::Index::Adapter::Base::BATCH_SIZE
|
|
37
37
|
}.freeze
|
|
@@ -56,6 +56,7 @@ module Chewy
|
|
|
56
56
|
{}
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
|
+
@context = @options[:context] || {}
|
|
59
60
|
@errors = []
|
|
60
61
|
@stats = {}
|
|
61
62
|
@leftovers = []
|
|
@@ -78,7 +79,7 @@ module Chewy
|
|
|
78
79
|
# @param delete [Array<Object>] any acceptable objects for deleting
|
|
79
80
|
# @return [true, false] the result of the request, true if no errors
|
|
80
81
|
def process(index: [], delete: [])
|
|
81
|
-
bulk_builder = BulkBuilder.new(@index, to_index: index, delete: delete, fields: @options[:update_fields])
|
|
82
|
+
bulk_builder = BulkBuilder.new(@index, to_index: index, delete: delete, fields: @options[:update_fields], context: @context)
|
|
82
83
|
bulk_body = bulk_builder.bulk_body
|
|
83
84
|
|
|
84
85
|
if @options[:journal]
|
data/lib/chewy/index/import.rb
CHANGED
|
@@ -2,6 +2,7 @@ require 'chewy/index/import/journal_builder'
|
|
|
2
2
|
require 'chewy/index/import/bulk_builder'
|
|
3
3
|
require 'chewy/index/import/bulk_request'
|
|
4
4
|
require 'chewy/index/import/routine'
|
|
5
|
+
require 'chewy/index/import/progressbar'
|
|
5
6
|
|
|
6
7
|
module Chewy
|
|
7
8
|
class Index
|
|
@@ -11,20 +12,22 @@ module Chewy
|
|
|
11
12
|
IMPORT_WORKER = lambda do |index, options, total, ids, iteration|
|
|
12
13
|
::Process.setproctitle("chewy [#{index}]: import data (#{iteration + 1}/#{total})")
|
|
13
14
|
routine = Routine.new(index, **options)
|
|
15
|
+
processed = 0
|
|
14
16
|
index.adapter.import(*ids, routine.options) do |action_objects|
|
|
15
17
|
routine.process(**action_objects)
|
|
18
|
+
processed += action_objects.sum { |_, v| v.size }
|
|
16
19
|
end
|
|
17
|
-
{errors: routine.errors, import: routine.stats, leftovers: routine.leftovers}
|
|
20
|
+
{errors: routine.errors, import: routine.stats, leftovers: routine.leftovers, processed: processed}
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
LEFTOVERS_WORKER = lambda do |index, options, total, body, iteration|
|
|
21
24
|
::Process.setproctitle("chewy [#{index}]: import leftovers (#{iteration + 1}/#{total})")
|
|
22
25
|
routine = Routine.new(index, **options)
|
|
23
26
|
routine.perform_bulk(body)
|
|
24
|
-
routine.errors
|
|
27
|
+
{errors: routine.errors}
|
|
25
28
|
end
|
|
26
29
|
|
|
27
|
-
module ClassMethods
|
|
30
|
+
module ClassMethods # rubocop:disable Metrics/ModuleLength
|
|
28
31
|
# @!method import(*collection, **options)
|
|
29
32
|
# Basically, one of the main methods for an index. Performs any objects import
|
|
30
33
|
# to the index. Does all the objects handling routines.
|
|
@@ -68,9 +71,15 @@ module Chewy
|
|
|
68
71
|
# @option options [Integer] batch_size passed to the adapter import method, used to split imported objects in chunks, 1000 by default
|
|
69
72
|
# @option options [Boolean] direct_import skips object reloading in ORM adapter, `false` by default
|
|
70
73
|
# @option options [true, false] journal enables imported objects journaling, false by default
|
|
71
|
-
# @option options [Array<Symbol, String>] update_fields list of fields for
|
|
74
|
+
# @option options [Array<Symbol, String>] update_fields list of fields for partial import. `nil` (default) triggers full document reindex;
|
|
75
|
+
# an empty array (`[]`) is an explicit no-op (no fields updated).
|
|
72
76
|
# @option options [true, false] update_failover enables full objects reimport in cases of partial update errors, `true` by default
|
|
73
77
|
# @option options [true, Integer, Hash] parallel enables parallel import processing with the Parallel gem, accepts the number of workers or any Parallel gem acceptable options
|
|
78
|
+
# @option options [true, false, :unbounded] progressbar shows an import progressbar
|
|
79
|
+
# on stderr. `true` precomputes the total via `adapter.import_count` (one extra
|
|
80
|
+
# count query); `:unbounded` shows a spinner without computing the total. Default
|
|
81
|
+
# `false`. Safe in parallel mode: the bar is incremented in the parent process via
|
|
82
|
+
# `Parallel`'s `finish:` callback, workers stay process-based.
|
|
74
83
|
# @return [true, false] false in case of errors
|
|
75
84
|
def import(*args)
|
|
76
85
|
intercept_import_using_strategy(*args).blank?
|
|
@@ -115,13 +124,13 @@ module Chewy
|
|
|
115
124
|
# @param crutches [Object] optional crutches object; if omitted - a crutch for the single passed object is created as a fallback
|
|
116
125
|
# @param fields [Array<Symbol>] and array of fields to restrict the generated document
|
|
117
126
|
# @return [Hash] a JSON-ready hash
|
|
118
|
-
def compose(object, crutches = nil, fields: [])
|
|
119
|
-
crutches ||= Chewy::Index::Crutch::Crutches.new self, [object]
|
|
127
|
+
def compose(object, crutches = nil, fields: [], context: {})
|
|
128
|
+
crutches ||= Chewy::Index::Crutch::Crutches.new self, [object], context
|
|
120
129
|
|
|
121
130
|
if witchcraft? && root.children.present?
|
|
122
|
-
cauldron(fields: fields).brew(object, crutches)
|
|
131
|
+
cauldron(fields: fields).brew(object, crutches, context)
|
|
123
132
|
else
|
|
124
|
-
root.compose(object, crutches, fields: fields)
|
|
133
|
+
root.compose(object, crutches, fields: fields, context: context)
|
|
125
134
|
end
|
|
126
135
|
end
|
|
127
136
|
|
|
@@ -175,46 +184,91 @@ module Chewy
|
|
|
175
184
|
end
|
|
176
185
|
|
|
177
186
|
def import_linear(objects, routine)
|
|
187
|
+
bar = build_progressbar(routine, objects)
|
|
178
188
|
ActiveSupport::Notifications.instrument 'import_objects.chewy', index: self do |payload|
|
|
179
189
|
adapter.import(*objects, routine.options) do |action_objects|
|
|
180
190
|
routine.process(**action_objects)
|
|
191
|
+
bar.increment(action_objects.sum { |_, v| v.size })
|
|
181
192
|
end
|
|
182
193
|
routine.perform_bulk(routine.leftovers)
|
|
183
194
|
payload[:import] = routine.stats
|
|
184
195
|
payload[:errors] = payload_errors(routine.errors) if routine.errors.present?
|
|
185
196
|
payload[:errors]
|
|
186
197
|
end
|
|
198
|
+
ensure
|
|
199
|
+
bar&.finish
|
|
187
200
|
end
|
|
188
201
|
|
|
189
202
|
def import_parallel(objects, routine)
|
|
190
203
|
raise "The `parallel` gem is required for parallel import, please add `gem 'parallel'` to your Gemfile" unless '::Parallel'.safe_constantize
|
|
191
204
|
|
|
205
|
+
bar = build_progressbar(routine, objects)
|
|
192
206
|
ActiveSupport::Notifications.instrument 'import_objects.chewy', index: self do |payload|
|
|
193
207
|
batches = adapter.import_references(*objects, routine.options.slice(:batch_size)).to_a
|
|
194
208
|
|
|
195
209
|
::ActiveRecord::Base.connection.close if defined?(::ActiveRecord::Base)
|
|
196
210
|
results = ::Parallel.map_with_index(
|
|
197
211
|
batches,
|
|
198
|
-
routine.parallel_options,
|
|
212
|
+
parallel_options_with_progress(routine.parallel_options, bar),
|
|
199
213
|
&IMPORT_WORKER.curry[self, routine.options, batches.size]
|
|
200
214
|
)
|
|
201
215
|
::ActiveRecord::Base.connection.reconnect! if defined?(::ActiveRecord::Base)
|
|
202
216
|
errors, import, leftovers = process_parallel_import_results(results)
|
|
203
|
-
|
|
204
|
-
if leftovers.present?
|
|
205
|
-
batches = leftovers.each_slice(routine.options[:batch_size])
|
|
206
|
-
results = ::Parallel.map_with_index(
|
|
207
|
-
batches,
|
|
208
|
-
routine.parallel_options,
|
|
209
|
-
&LEFTOVERS_WORKER.curry[self, routine.options, batches.size]
|
|
210
|
-
)
|
|
211
|
-
errors.concat(results.flatten(1))
|
|
212
|
-
end
|
|
217
|
+
errors.concat(process_parallel_leftovers(leftovers, routine)) if leftovers.present?
|
|
213
218
|
|
|
214
219
|
payload[:import] = import
|
|
215
220
|
payload[:errors] = payload_errors(errors) if errors.present?
|
|
216
221
|
payload[:errors]
|
|
217
222
|
end
|
|
223
|
+
ensure
|
|
224
|
+
bar&.finish
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def process_parallel_leftovers(leftovers, routine)
|
|
228
|
+
batches = leftovers.each_slice(routine.options[:batch_size]).to_a
|
|
229
|
+
results = ::Parallel.map_with_index(
|
|
230
|
+
batches,
|
|
231
|
+
routine.parallel_options,
|
|
232
|
+
&LEFTOVERS_WORKER.curry[self, routine.options, batches.size]
|
|
233
|
+
)
|
|
234
|
+
results.flat_map { |r| r[:errors] }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Builds Parallel options with a `finish:` callback that increments the
|
|
238
|
+
# progressbar after each worker batch returns. The callback runs in the
|
|
239
|
+
# parent (main) thread under Parallel's internal mutex (parallel-1.x),
|
|
240
|
+
# so workers stay process-based and there is no worker-side
|
|
241
|
+
# synchronization — the regression that triggered the PR #800 revert.
|
|
242
|
+
#
|
|
243
|
+
# If the caller already supplied a `finish:` callback in
|
|
244
|
+
# `parallel_options`, both run; user callback first, then the bar.
|
|
245
|
+
def parallel_options_with_progress(parallel_options, bar)
|
|
246
|
+
user_finish = parallel_options[:finish]
|
|
247
|
+
progress = lambda do |item, i, result|
|
|
248
|
+
user_finish&.call(item, i, result)
|
|
249
|
+
bar.increment(result[:processed]) if result.is_a?(Hash) && result[:processed]
|
|
250
|
+
end
|
|
251
|
+
parallel_options.merge(finish: progress)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def build_progressbar(routine, objects)
|
|
255
|
+
enabled = routine.options[:progressbar]
|
|
256
|
+
total = enabled == true ? safe_import_count(objects) : nil
|
|
257
|
+
Progressbar.build(enabled, total)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Returns nil when the adapter cannot or should not be counted:
|
|
261
|
+
# missing `import_count` on a custom adapter, a grouped scope that
|
|
262
|
+
# raises, or any unexpected count failure. A nil total makes
|
|
263
|
+
# `Progressbar.new` render a spinner instead of a bounded bar —
|
|
264
|
+
# avoids aborting the import just because the progressbar can't
|
|
265
|
+
# size itself.
|
|
266
|
+
def safe_import_count(objects)
|
|
267
|
+
return nil unless adapter.respond_to?(:import_count)
|
|
268
|
+
|
|
269
|
+
adapter.import_count(*objects)
|
|
270
|
+
rescue StandardError
|
|
271
|
+
nil
|
|
218
272
|
end
|
|
219
273
|
|
|
220
274
|
def process_parallel_import_results(results)
|
|
@@ -59,15 +59,15 @@ module Chewy
|
|
|
59
59
|
@fields = fields
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
def brew(object, crutches = nil)
|
|
63
|
-
alicorn.call(locals, object, crutches).as_json
|
|
62
|
+
def brew(object, crutches = nil, context = {})
|
|
63
|
+
alicorn.call(locals, object, crutches, context).as_json
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
private
|
|
67
67
|
|
|
68
68
|
def alicorn
|
|
69
69
|
@alicorn ||= singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
70
|
-
-> (locals, object0, crutches) do
|
|
70
|
+
-> (locals, object0, crutches, context) do
|
|
71
71
|
#{composed_values(@index.root, 0)}
|
|
72
72
|
end
|
|
73
73
|
RUBY
|
|
@@ -171,7 +171,7 @@ module Chewy
|
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
-
def source_for(proc, nesting)
|
|
174
|
+
def source_for(proc, nesting) # rubocop:disable Metrics/AbcSize
|
|
175
175
|
lambdas = exctract_lambdas(ast_from_proc(proc))
|
|
176
176
|
|
|
177
177
|
raise "No lambdas found, try to reformat your code:\n`#{proc.source}`" unless lambdas
|
|
@@ -189,6 +189,7 @@ module Chewy
|
|
|
189
189
|
source = replace_lvar(source, proc_params[n], :"object#{n}") if proc_params[n]
|
|
190
190
|
end
|
|
191
191
|
source = replace_lvar(source, proc_params[nesting + 1], :crutches) if proc_params[nesting + 1]
|
|
192
|
+
source = replace_lvar(source, proc_params[nesting + 2], :context) if proc_params[nesting + 2]
|
|
192
193
|
|
|
193
194
|
binding_variable_list(source).each do |variable|
|
|
194
195
|
locals.push(proc.binding.eval(variable.to_s))
|
data/lib/chewy/multi_search.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Chewy
|
|
|
11
11
|
# Instantiate a new MultiSearch instance.
|
|
12
12
|
#
|
|
13
13
|
# @param queries [Array<Chewy::Search::Request>]
|
|
14
|
-
# @option [Elasticsearch::
|
|
14
|
+
# @option [Elasticsearch::Client] :client (Chewy.client)
|
|
15
15
|
# The Elasticsearch client that should be used for issuing requests.
|
|
16
16
|
def initialize(queries, client: Chewy.client)
|
|
17
17
|
@client = client
|
data/lib/chewy/rake_helper.rb
CHANGED
|
@@ -21,6 +21,8 @@ module Chewy
|
|
|
21
21
|
|
|
22
22
|
DELETE_BY_QUERY_OPTIONS = %w[WAIT_FOR_COMPLETION REQUESTS_PER_SECOND SCROLL_SIZE].freeze
|
|
23
23
|
FALSE_VALUES = %w[0 f false off].freeze
|
|
24
|
+
TRUE_VALUES = %w[1 t true on yes].freeze
|
|
25
|
+
UNBOUNDED_VALUES = %w[unbounded].freeze
|
|
24
26
|
|
|
25
27
|
class << self
|
|
26
28
|
# Performs zero-downtime reindexing of all documents for the specified indexes
|
|
@@ -105,7 +107,7 @@ module Chewy
|
|
|
105
107
|
indexes_from(only: only, except: except).each_with_object([]) do |index, updated_indexes|
|
|
106
108
|
if index.exists?
|
|
107
109
|
output.puts "Updating #{index}"
|
|
108
|
-
index.import(parallel: parallel)
|
|
110
|
+
index.import(parallel: parallel, progressbar: progressbar_option)
|
|
109
111
|
updated_indexes.push(index)
|
|
110
112
|
else
|
|
111
113
|
output.puts "Skipping #{index}, it does not exists (use rake chewy:reset[#{index.derivable_name}] to create and update it)"
|
|
@@ -336,7 +338,22 @@ module Chewy
|
|
|
336
338
|
|
|
337
339
|
def reset_one(index, output, parallel: false)
|
|
338
340
|
output.puts "Resetting #{index}"
|
|
339
|
-
index.reset!((Time.now.to_f * 1000).round, parallel: parallel, apply_journal: journal_exists
|
|
341
|
+
index.reset!((Time.now.to_f * 1000).round, parallel: parallel, apply_journal: journal_exists?, progressbar: progressbar_option)
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def progressbar_option
|
|
345
|
+
value = ENV.fetch('PROGRESS', nil)
|
|
346
|
+
return false if value.nil? || value.empty?
|
|
347
|
+
|
|
348
|
+
case value.downcase
|
|
349
|
+
when *FALSE_VALUES then false
|
|
350
|
+
when *UNBOUNDED_VALUES then :unbounded
|
|
351
|
+
when *TRUE_VALUES then true
|
|
352
|
+
else
|
|
353
|
+
warn "PROGRESS=#{value.inspect} not recognized; treating as enabled. " \
|
|
354
|
+
"Use #{TRUE_VALUES.join('/')}, #{UNBOUNDED_VALUES.join('/')}, or #{FALSE_VALUES.join('/')}."
|
|
355
|
+
true
|
|
356
|
+
end
|
|
340
357
|
end
|
|
341
358
|
|
|
342
359
|
def warn_missing_index(output)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Chewy
|
|
2
|
+
module Search
|
|
3
|
+
class Parameters
|
|
4
|
+
# Just a standard hash storage. Nothing to see here.
|
|
5
|
+
#
|
|
6
|
+
# @see Chewy::Search::Parameters::HashStorage
|
|
7
|
+
# @see Chewy::Search::Request#runtime_mappings
|
|
8
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-search-request.html
|
|
9
|
+
class RuntimeMappings < Storage
|
|
10
|
+
include HashStorage
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/chewy/search/request.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Chewy
|
|
|
25
25
|
search_type preference limit offset terminate_after
|
|
26
26
|
timeout min_score source stored_fields search_after
|
|
27
27
|
load script_fields suggest aggs aggregations collapse none
|
|
28
|
-
indices_boost rescore highlight total total_count
|
|
28
|
+
indices_boost rescore highlight runtime_mappings total total_count
|
|
29
29
|
total_entries indices types delete_all count exists?
|
|
30
30
|
exist? find pluck scroll_batches scroll_hits
|
|
31
31
|
scroll_results scroll_wrappers ignore_unavailable
|
|
@@ -656,7 +656,23 @@ module Chewy
|
|
|
656
656
|
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/highlighting.html
|
|
657
657
|
# @param value [Hash]
|
|
658
658
|
# @return [Chewy::Search::Request]
|
|
659
|
-
|
|
659
|
+
#
|
|
660
|
+
# @!method runtime_mappings(value)
|
|
661
|
+
# Add a `runtime_mappings` part to the request. Further
|
|
662
|
+
# call values are merged to the storage hash.
|
|
663
|
+
#
|
|
664
|
+
# @example
|
|
665
|
+
# PlacesIndex
|
|
666
|
+
# .runtime_mappings(field1: {type: "keyword", script: {lang: "painless", source: "emit('some script here')"}})
|
|
667
|
+
# .runtime_mappings(field2: {type: "keyword", script: {lang: "painless", source: "emit('some script here')"}})
|
|
668
|
+
# # => <PlacesIndex::Query {..., :body=>{:runtime_mappings=>{
|
|
669
|
+
# # "field1"=>{:type=>"keyword", :script=>{:lang=>"painless", :source=>"emit('some script here')"}},
|
|
670
|
+
# # "field2"=>{:type=>"keyword", :script=>{:lang=>"painless", :source=>"emit('some script here')"}}}}}>
|
|
671
|
+
# @see Chewy::Search::Parameters::RuntimeMappings
|
|
672
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-search-request.html
|
|
673
|
+
# @param value [Hash]
|
|
674
|
+
# @return [Chewy::Search::Request]
|
|
675
|
+
%i[script_fields indices_boost rescore highlight runtime_mappings].each do |name|
|
|
660
676
|
define_method name do |value|
|
|
661
677
|
modify(name) { update!(value) }
|
|
662
678
|
end
|
|
@@ -29,20 +29,28 @@ module Chewy
|
|
|
29
29
|
|
|
30
30
|
result = perform(size: batch_size, scroll: scroll)
|
|
31
31
|
total = [raw_limit_value, result.fetch('hits', {}).fetch('total', {}).fetch('value', 0)].compact.min
|
|
32
|
+
|
|
33
|
+
total_batches = total / batch_size
|
|
32
34
|
last_batch_size = total % batch_size
|
|
33
|
-
|
|
35
|
+
|
|
36
|
+
total_batches += 1 if last_batch_size != 0
|
|
37
|
+
|
|
34
38
|
scroll_id = nil
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
total_batches.times do |batch_counter|
|
|
41
|
+
last_run = total_batches - 1 == batch_counter
|
|
42
|
+
|
|
37
43
|
hits = result.fetch('hits', {}).fetch('hits', [])
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
hits = hits.first(last_batch_size) if last_run && last_batch_size != 0
|
|
45
|
+
|
|
46
|
+
raise Chewy::MissingHitsInScrollError if hits.empty?
|
|
47
|
+
|
|
40
48
|
yield(hits) if hits.present?
|
|
41
49
|
scroll_id = result['_scroll_id']
|
|
42
50
|
|
|
43
|
-
break if result['terminated_early']
|
|
51
|
+
break if result['terminated_early']
|
|
44
52
|
|
|
45
|
-
result = perform_scroll(scroll: scroll, scroll_id: scroll_id)
|
|
53
|
+
result = perform_scroll(scroll: scroll, scroll_id: scroll_id) unless last_run
|
|
46
54
|
end
|
|
47
55
|
ensure
|
|
48
56
|
Chewy.client.clear_scroll(body: {scroll_id: scroll_id}) if scroll_id
|
data/lib/chewy/stash.rb
CHANGED
|
@@ -38,17 +38,21 @@ module Chewy
|
|
|
38
38
|
|
|
39
39
|
# Selects all the journal entries for the specified indices.
|
|
40
40
|
#
|
|
41
|
+
# Uses a single `terms` filter rather than a chain of `bool.should`
|
|
42
|
+
# clauses so the query depth stays constant regardless of how many
|
|
43
|
+
# indices are passed. Avoids hitting the Elasticsearch
|
|
44
|
+
# `indices.query.bool.max_nested_depth` limit (default 30) when
|
|
45
|
+
# cleaning or applying journals across many indices.
|
|
46
|
+
#
|
|
41
47
|
# @param indices [Chewy::Index, Array<Chewy::Index>]
|
|
42
48
|
def self.for(*something)
|
|
43
49
|
something = something.flatten.compact
|
|
50
|
+
return all if something.empty?
|
|
51
|
+
|
|
44
52
|
indexes = something.flat_map { |s| Chewy.derive_name(s) }
|
|
45
|
-
return none if
|
|
53
|
+
return none if indexes.blank?
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
indexes.each do |index|
|
|
49
|
-
scope = scope.or(filter(term: {index_name: index.derivable_name}))
|
|
50
|
-
end
|
|
51
|
-
scope
|
|
55
|
+
filter(terms: {index_name: indexes.map(&:derivable_name).uniq})
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
default_import_options journal: false
|
|
@@ -13,7 +13,7 @@ module Chewy
|
|
|
13
13
|
local timechunks_key = prefix .. ":" .. type .. ":timechunks"
|
|
14
14
|
|
|
15
15
|
-- Get timechunk_keys with scores less than or equal to the specified score
|
|
16
|
-
local timechunk_keys = redis.call('
|
|
16
|
+
local timechunk_keys = redis.call('zrange', timechunks_key, '-inf', score, 'byscore')
|
|
17
17
|
|
|
18
18
|
-- Get all members from the sets associated with the timechunk_keys
|
|
19
19
|
local members = {}
|
data/lib/chewy/version.rb
CHANGED
data/lib/chewy.rb
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chewy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.0
|
|
4
|
+
version: 8.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Toptal, LLC
|
|
8
8
|
- pyromaniac
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: activesupport
|
|
@@ -89,6 +88,7 @@ files:
|
|
|
89
88
|
- lib/chewy/index/import/bulk_builder.rb
|
|
90
89
|
- lib/chewy/index/import/bulk_request.rb
|
|
91
90
|
- lib/chewy/index/import/journal_builder.rb
|
|
91
|
+
- lib/chewy/index/import/progressbar.rb
|
|
92
92
|
- lib/chewy/index/import/routine.rb
|
|
93
93
|
- lib/chewy/index/mapping.rb
|
|
94
94
|
- lib/chewy/index/observe.rb
|
|
@@ -147,6 +147,7 @@ files:
|
|
|
147
147
|
- lib/chewy/search/parameters/query.rb
|
|
148
148
|
- lib/chewy/search/parameters/request_cache.rb
|
|
149
149
|
- lib/chewy/search/parameters/rescore.rb
|
|
150
|
+
- lib/chewy/search/parameters/runtime_mappings.rb
|
|
150
151
|
- lib/chewy/search/parameters/script_fields.rb
|
|
151
152
|
- lib/chewy/search/parameters/search_after.rb
|
|
152
153
|
- lib/chewy/search/parameters/search_type.rb
|
|
@@ -186,7 +187,6 @@ licenses:
|
|
|
186
187
|
- MIT
|
|
187
188
|
metadata:
|
|
188
189
|
rubygems_mfa_required: 'true'
|
|
189
|
-
post_install_message:
|
|
190
190
|
rdoc_options: []
|
|
191
191
|
require_paths:
|
|
192
192
|
- lib
|
|
@@ -201,8 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
201
201
|
- !ruby/object:Gem::Version
|
|
202
202
|
version: '0'
|
|
203
203
|
requirements: []
|
|
204
|
-
rubygems_version:
|
|
205
|
-
signing_key:
|
|
204
|
+
rubygems_version: 4.0.12
|
|
206
205
|
specification_version: 4
|
|
207
206
|
summary: Elasticsearch ODM client wrapper
|
|
208
207
|
test_files: []
|