esse 0.3.4 → 0.4.0.rc1
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/lib/esse/cli/event_listener.rb +7 -0
- data/lib/esse/cli/index.rb +21 -14
- data/lib/esse/cli/templates/config.rb.erb +4 -2
- data/lib/esse/config.rb +5 -2
- data/lib/esse/core.rb +7 -0
- data/lib/esse/document.rb +23 -7
- data/lib/esse/document_for_partial_update.rb +16 -0
- data/lib/esse/events.rb +2 -0
- data/lib/esse/import/bulk.rb +17 -13
- data/lib/esse/index/documents.rb +108 -29
- data/lib/esse/index/indices.rb +24 -17
- data/lib/esse/index/object_document_mapper.rb +1 -1
- data/lib/esse/index/settings.rb +22 -3
- data/lib/esse/lazy_document_header.rb +39 -27
- data/lib/esse/primitives/hash_utils.rb +10 -0
- data/lib/esse/repository/documents.rb +5 -6
- data/lib/esse/repository/object_document_mapper.rb +47 -9
- data/lib/esse/transport/indices.rb +77 -0
- data/lib/esse/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6023e2f4fe6b5d8e45dd09e7c98bb250d8862ea3adc769f119011efc07191c5
|
4
|
+
data.tar.gz: 852a46c60435d7c0848254d6b79a4a29ee89efe9e0700975d7d651660ad874d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40b5c6d0ed7ff8ce793cd8be088c01f9377c62cf58366b201c8ee988f04e9f2f3e53118a48c165857394dc100c26fd06b300d653f2afdead076430d19210c554
|
7
|
+
data.tar.gz: f3b4f4acadea569ef1108c1d3d3a2745c965177c29f307e5076357d89aec1f050f778933a350ccb75c0128a295d0f1349899452ea041551fae8ae574fb75793d
|
@@ -95,6 +95,13 @@ module Esse
|
|
95
95
|
end
|
96
96
|
print_message(stats.join(', ') + '.')
|
97
97
|
end
|
98
|
+
|
99
|
+
def elasticsearch_reindex(event)
|
100
|
+
print_message '[%<runtime>s] Reindex from %<from>s to %<to>s successfuly completed',
|
101
|
+
from: colorize(event[:request].dig(:body, :source, :index), :bold),
|
102
|
+
to: colorize(event[:request].dig(:body, :dest, :index), :bold),
|
103
|
+
runtime: formatted_runtime(event[:runtime])
|
104
|
+
end
|
98
105
|
end
|
99
106
|
end
|
100
107
|
end
|
data/lib/esse/cli/index.rb
CHANGED
@@ -16,14 +16,18 @@ module Esse
|
|
16
16
|
DESC
|
17
17
|
option :suffix, type: :string, default: nil, aliases: '-s', desc: 'Suffix to append to index name'
|
18
18
|
option :import, type: :boolean, default: true, desc: 'Import documents before point alias to the new index'
|
19
|
+
option :reindex, type: :boolean, default: false, desc: 'Use _reindex API to import documents from the old index to the new index'
|
19
20
|
option :optimize, type: :boolean, default: true, desc: 'Optimize index before import documents by disabling refresh_interval and setting number_of_replicas to 0'
|
21
|
+
option :settings, type: :hash, default: nil, desc: 'List of settings to pass to the index class. Example: --settings=refresh_interval:1s,number_of_replicas:0'
|
20
22
|
def reset(*index_classes)
|
21
23
|
require_relative 'index/reset'
|
22
|
-
|
24
|
+
opts = HashUtils.deep_transform_keys(options.to_h, &:to_sym)
|
25
|
+
if opts[:import] && opts[:reindex]
|
26
|
+
raise ArgumentError, 'You cannot use --import and --reindex together'
|
27
|
+
end
|
28
|
+
Reset.new(indices: index_classes, **opts).run
|
23
29
|
end
|
24
30
|
|
25
|
-
# @TODO Add reindex task to create a new index and import documents from the old index using _reindex API
|
26
|
-
|
27
31
|
desc 'create *INDEX_CLASSES', 'Creates indices for the given classes'
|
28
32
|
long_desc <<-DESC
|
29
33
|
Creates index and applies mapping and settings for the given classes.
|
@@ -33,9 +37,11 @@ module Esse
|
|
33
37
|
DESC
|
34
38
|
option :suffix, type: :string, default: nil, aliases: '-s', desc: 'Suffix to append to index name'
|
35
39
|
option :alias, type: :boolean, default: false, aliases: '-a', desc: 'Update alias after create index'
|
40
|
+
option :settings, type: :hash, default: nil, desc: 'List of settings to pass to the index class. Example: --settings=index.refresh_interval:-1,index.number_of_replicas:0'
|
36
41
|
def create(*index_classes)
|
37
42
|
require_relative 'index/create'
|
38
|
-
|
43
|
+
opts = HashUtils.deep_transform_keys(options.to_h, &:to_sym)
|
44
|
+
Create.new(indices: index_classes, **opts).run
|
39
45
|
end
|
40
46
|
|
41
47
|
desc 'delete *INDEX_CLASSES', 'Deletes indices for the given classes'
|
@@ -58,9 +64,11 @@ module Esse
|
|
58
64
|
desc 'update_settings *INDEX_CLASS', 'Closes the index for read/write operations, updates the index settings, and open it again'
|
59
65
|
option :suffix, type: :string, default: nil, aliases: '-s', desc: 'Suffix to append to index name'
|
60
66
|
option :type, type: :string, default: nil, aliases: '-t', desc: 'Document Type to update mapping for'
|
67
|
+
option :settings, type: :hash, default: nil, desc: 'List of settings to pass to the index class. Example: --settings=index.refresh_interval:-1,index.number_of_replicas:0'
|
61
68
|
def update_settings(*index_classes)
|
62
69
|
require_relative 'index/update_settings'
|
63
|
-
|
70
|
+
opts = HashUtils.deep_transform_keys(options.to_h, &:to_sym)
|
71
|
+
UpdateSettings.new(indices: index_classes, **opts).run
|
64
72
|
end
|
65
73
|
|
66
74
|
desc 'update_mapping *INDEX_CLASS', 'Create or update a mapping'
|
@@ -89,18 +97,17 @@ module Esse
|
|
89
97
|
option :suffix, type: :string, default: nil, aliases: '-s', desc: 'Suffix to append to index name'
|
90
98
|
option :context, type: :hash, default: {}, required: true, desc: 'List of options to pass to the index class'
|
91
99
|
option :repo, type: :string, default: nil, alias: '-r', desc: 'Repository to use for import'
|
92
|
-
option :
|
93
|
-
option :
|
100
|
+
option :preload_lazy_attributes, type: :string, default: nil, desc: 'Command separated list of lazy document attributes to preload using search API before the bulk import. Or pass `true` to preload all lazy attributes'
|
101
|
+
option :eager_load_lazy_attributes, type: :string, default: nil, desc: 'Comma separated list of lazy document attributes to include to the bulk index request. Or pass `true` to include all lazy attributes'
|
102
|
+
option :update_lazy_attributes, type: :string, default: nil, desc: 'Comma separated list of lazy document attributes to bulk update after the bulk index request Or pass `true` to include all lazy attributes'
|
103
|
+
|
94
104
|
def import(*index_classes)
|
95
105
|
require_relative 'index/import'
|
96
106
|
opts = HashUtils.deep_transform_keys(options.to_h, &:to_sym)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
if (val = opts[:lazy_update_document_attributes])
|
103
|
-
opts[:lazy_update_document_attributes] = (val == 'true') ? true : val.split(',')
|
107
|
+
%i[preload_lazy_attributes eager_load_lazy_attributes update_lazy_attributes].each do |key|
|
108
|
+
if (val = opts.delete(key)) && val != 'false'
|
109
|
+
opts[key] = (val == 'true') ? true : val.split(',')
|
110
|
+
end
|
104
111
|
end
|
105
112
|
Import.new(indices: index_classes, **opts).run
|
106
113
|
end
|
data/lib/esse/config.rb
CHANGED
@@ -10,8 +10,11 @@ module Esse
|
|
10
10
|
# cluster.index_prefix = 'backend'
|
11
11
|
# cluster.client = Elasticsearch::Client.new
|
12
12
|
# cluster.settings = {
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# index: {
|
14
|
+
# number_of_shards: 2,
|
15
|
+
# number_of_replicas: 1
|
16
|
+
# },
|
17
|
+
# analysis: { ... }
|
15
18
|
# }
|
16
19
|
# cluster.mappings = {
|
17
20
|
# dynamic_templates: [...]
|
data/lib/esse/core.rb
CHANGED
@@ -6,6 +6,7 @@ module Esse
|
|
6
6
|
require_relative 'primitives'
|
7
7
|
require_relative 'collection'
|
8
8
|
require_relative 'document'
|
9
|
+
require_relative 'document_for_partial_update'
|
9
10
|
require_relative 'document_lazy_attribute'
|
10
11
|
require_relative 'lazy_document_header'
|
11
12
|
require_relative 'hash_document'
|
@@ -91,4 +92,10 @@ module Esse
|
|
91
92
|
|
92
93
|
!!(object.is_a?(Esse::Document) && object.id)
|
93
94
|
end
|
95
|
+
|
96
|
+
def self.document_match_with_header?(document, id, routing, type)
|
97
|
+
id && id.to_s == document.id.to_s &&
|
98
|
+
routing == document.routing &&
|
99
|
+
(LazyDocumentHeader::ACCEPTABLE_DOC_TYPES.include?(document.type) && LazyDocumentHeader::ACCEPTABLE_DOC_TYPES.include?(type) || document.type == type)
|
100
|
+
end
|
94
101
|
end
|
data/lib/esse/document.rb
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
module Esse
|
4
4
|
class Document
|
5
|
+
MUTATIONS_FALLBACK = {}.freeze
|
6
|
+
|
5
7
|
attr_reader :object, :options
|
6
8
|
|
7
9
|
def initialize(object, **options)
|
8
10
|
@object = object
|
9
|
-
@options = options
|
11
|
+
@options = options.freeze
|
10
12
|
end
|
11
13
|
|
12
14
|
# @return [String, Number] the document ID
|
@@ -84,11 +86,16 @@ module Esse
|
|
84
86
|
id.nil?
|
85
87
|
end
|
86
88
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
def eql?(other, match_lazy_doc_header: false)
|
90
|
+
if match_lazy_doc_header
|
91
|
+
other.eql?(self)
|
92
|
+
else
|
93
|
+
other.is_a?(Esse::Document) && (
|
94
|
+
id.to_s == other.id.to_s && type == other.type && routing == other.routing && meta == other.meta
|
95
|
+
)
|
96
|
+
end
|
91
97
|
end
|
98
|
+
alias_method :==, :eql?
|
92
99
|
|
93
100
|
def doc_header
|
94
101
|
{ _id: id }.tap do |h|
|
@@ -97,10 +104,17 @@ module Esse
|
|
97
104
|
end
|
98
105
|
end
|
99
106
|
|
107
|
+
def document_for_partial_update(source)
|
108
|
+
DocumentForPartialUpdate.new(self, source: source)
|
109
|
+
end
|
110
|
+
|
100
111
|
def inspect
|
101
112
|
attributes = %i[id routing source].map do |attr|
|
102
113
|
value = send(attr)
|
103
|
-
|
114
|
+
next unless value
|
115
|
+
"#{attr}: #{value.inspect}"
|
116
|
+
rescue
|
117
|
+
nil
|
104
118
|
end.compact.join(', ')
|
105
119
|
attributes << " mutations: #{@__mutations__.inspect}" if @__mutations__
|
106
120
|
"#<#{self.class.name || 'Esse::Document'} #{attributes}>"
|
@@ -112,7 +126,9 @@ module Esse
|
|
112
126
|
instance_variable_set(:@__mutated_source__, nil)
|
113
127
|
end
|
114
128
|
|
115
|
-
|
129
|
+
def mutations
|
130
|
+
@__mutations__ || MUTATIONS_FALLBACK
|
131
|
+
end
|
116
132
|
|
117
133
|
def mutated_source
|
118
134
|
return source unless @__mutations__
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
class DocumentForPartialUpdate < Esse::Document
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators :object, :id, :type, :routing, :options
|
8
|
+
|
9
|
+
attr_reader :source
|
10
|
+
|
11
|
+
def initialize(lazy_header, source:)
|
12
|
+
@source = source
|
13
|
+
super(lazy_header)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/esse/events.rb
CHANGED
data/lib/esse/import/bulk.rb
CHANGED
@@ -1,27 +1,35 @@
|
|
1
1
|
module Esse
|
2
2
|
module Import
|
3
3
|
class Bulk
|
4
|
-
def
|
5
|
-
|
4
|
+
def self.build_from_documents(type: nil, index: nil, delete: nil, create: nil, update: nil)
|
5
|
+
index = Array(index).select(&Esse.method(:document?)).reject(&:ignore_on_index?).map do |doc|
|
6
6
|
value = doc.to_bulk
|
7
7
|
value[:_type] ||= type if type
|
8
|
-
|
8
|
+
value
|
9
9
|
end
|
10
|
-
|
10
|
+
create = Array(create).select(&Esse.method(:document?)).reject(&:ignore_on_index?).map do |doc|
|
11
11
|
value = doc.to_bulk
|
12
12
|
value[:_type] ||= type if type
|
13
|
-
|
13
|
+
value
|
14
14
|
end
|
15
|
-
|
15
|
+
update = Array(update).select(&Esse.method(:document?)).reject(&:ignore_on_index?).map do |doc|
|
16
16
|
value = doc.to_bulk(operation: :update)
|
17
17
|
value[:_type] ||= type if type
|
18
|
-
|
18
|
+
value
|
19
19
|
end
|
20
|
-
|
20
|
+
delete = Array(delete).select(&Esse.method(:document?)).reject(&:ignore_on_delete?).map do |doc|
|
21
21
|
value = doc.to_bulk(data: false)
|
22
22
|
value[:_type] ||= type if type
|
23
|
-
|
23
|
+
value
|
24
24
|
end
|
25
|
+
new(index: index, delete: delete, create: create, update: update)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(index: nil, delete: nil, create: nil, update: nil)
|
29
|
+
@index = Esse::ArrayUtils.wrap(index).map { |payload| { index: payload } }
|
30
|
+
@create = Esse::ArrayUtils.wrap(create).map { |payload| { create: payload } }
|
31
|
+
@update = Esse::ArrayUtils.wrap(update).map { |payload| { update: payload } }
|
32
|
+
@delete = Esse::ArrayUtils.wrap(delete).map { |payload| { delete: payload } }
|
25
33
|
end
|
26
34
|
|
27
35
|
# Return an array of RequestBody instances
|
@@ -68,10 +76,6 @@ module Esse
|
|
68
76
|
|
69
77
|
private
|
70
78
|
|
71
|
-
def valid_doc?(doc)
|
72
|
-
Esse.document?(doc)
|
73
|
-
end
|
74
|
-
|
75
79
|
def optimistic_request
|
76
80
|
request = Import::RequestBodyAsJson.new
|
77
81
|
request.create = @create
|
data/lib/esse/index/documents.rb
CHANGED
@@ -114,7 +114,7 @@ module Esse
|
|
114
114
|
def update(doc = nil, suffix: nil, **options)
|
115
115
|
if document?(doc)
|
116
116
|
options[:id] = doc.id
|
117
|
-
options[:body] = { doc: doc.
|
117
|
+
options[:body] = { doc: doc.mutated_source }
|
118
118
|
options[:type] = doc.type if doc.type?
|
119
119
|
options[:routing] = doc.routing if doc.routing?
|
120
120
|
end
|
@@ -140,7 +140,7 @@ module Esse
|
|
140
140
|
def index(doc = nil, suffix: nil, **options)
|
141
141
|
if document?(doc)
|
142
142
|
options[:id] = doc.id
|
143
|
-
options[:body] = doc.
|
143
|
+
options[:body] = doc.mutated_source
|
144
144
|
options[:type] = doc.type if doc.type?
|
145
145
|
options[:routing] = doc.routing if doc.routing?
|
146
146
|
end
|
@@ -171,13 +171,53 @@ module Esse
|
|
171
171
|
}.merge(options)
|
172
172
|
cluster.may_update_type!(definition)
|
173
173
|
|
174
|
+
to_index = []
|
175
|
+
to_create = []
|
176
|
+
to_update = []
|
177
|
+
to_delete = []
|
178
|
+
Esse::ArrayUtils.wrap(index).each do |doc|
|
179
|
+
if doc.is_a?(Hash)
|
180
|
+
to_index << doc
|
181
|
+
elsif Esse.document?(doc) && !doc.ignore_on_index?
|
182
|
+
hash = doc.to_bulk
|
183
|
+
hash[:_type] ||= type if type
|
184
|
+
to_index << hash
|
185
|
+
end
|
186
|
+
end
|
187
|
+
Esse::ArrayUtils.wrap(create).each do |doc|
|
188
|
+
if doc.is_a?(Hash)
|
189
|
+
to_create << doc
|
190
|
+
elsif Esse.document?(doc) && !doc.ignore_on_index?
|
191
|
+
hash = doc.to_bulk
|
192
|
+
hash[:_type] ||= type if type
|
193
|
+
to_create << hash
|
194
|
+
end
|
195
|
+
end
|
196
|
+
Esse::ArrayUtils.wrap(update).each do |doc|
|
197
|
+
if doc.is_a?(Hash)
|
198
|
+
to_update << doc
|
199
|
+
elsif Esse.document?(doc) && !doc.ignore_on_index?
|
200
|
+
hash = doc.to_bulk(operation: :update)
|
201
|
+
hash[:_type] ||= type if type
|
202
|
+
to_update << hash
|
203
|
+
end
|
204
|
+
end
|
205
|
+
Esse::ArrayUtils.wrap(delete).each do |doc|
|
206
|
+
if doc.is_a?(Hash)
|
207
|
+
to_delete << doc
|
208
|
+
elsif Esse.document?(doc) && !doc.ignore_on_delete?
|
209
|
+
hash = doc.to_bulk(data: false)
|
210
|
+
hash[:_type] ||= type if type
|
211
|
+
to_delete << hash
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
174
215
|
# @TODO Wrap the return in a some other Stats object with more information
|
175
216
|
Esse::Import::Bulk.new(
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
update: update,
|
217
|
+
create: to_create,
|
218
|
+
delete: to_delete,
|
219
|
+
index: to_index,
|
220
|
+
update: to_update,
|
181
221
|
).each_request do |request_body|
|
182
222
|
cluster.api.bulk(**definition, body: request_body.body) do |event_payload|
|
183
223
|
event_payload[:body_stats] = request_body.stats
|
@@ -198,36 +238,61 @@ module Esse
|
|
198
238
|
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
199
239
|
# @option [Hash] :context The collection context. This value will be passed as argument to the collection
|
200
240
|
# May be SQL condition or any other filter you have defined on the collection.
|
241
|
+
# @option [Boolean, Array<String>] :eager_load_lazy_attributes A list of lazy document attributes to include to the bulk index request.
|
242
|
+
# Or pass `true` to include all lazy attributes.
|
243
|
+
# @option [Boolean, Array<String>] :update_lazy_attributes A list of lazy document attributes to bulk update each after the bulk import.
|
244
|
+
# Or pass `true` to update all lazy attributes.
|
245
|
+
# @option [Boolean, Array<String>] :preload_lazy_attributes A list of lazy document attributes to preload using search API before the bulk import.
|
246
|
+
# Or pass `true` to preload all lazy attributes.
|
201
247
|
# @return [Numeric] The number of documents imported
|
202
|
-
def import(*repo_types, context: {},
|
248
|
+
def import(*repo_types, context: {}, eager_load_lazy_attributes: false, update_lazy_attributes: false, preload_lazy_attributes: false, suffix: nil, **options)
|
203
249
|
repo_types = repo_hash.keys if repo_types.empty?
|
204
250
|
count = 0
|
205
251
|
|
252
|
+
if options.key?(:eager_include_document_attributes)
|
253
|
+
warn 'The `eager_include_document_attributes` option is deprecated. Use `eager_load_lazy_attributes` instead.'
|
254
|
+
eager_load_lazy_attributes = options.delete(:eager_include_document_attributes)
|
255
|
+
end
|
256
|
+
if options.key?(:lazy_update_document_attributes)
|
257
|
+
warn 'The `lazy_update_document_attributes` option is deprecated. Use `update_lazy_attributes` instead.'
|
258
|
+
update_lazy_attributes = options.delete(:lazy_update_document_attributes)
|
259
|
+
end
|
260
|
+
|
206
261
|
repo_hash.slice(*repo_types).each do |repo_name, repo|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
262
|
+
# Elasticsearch 6.x and older have multiple types per index.
|
263
|
+
# This gem supports multiple types per index for backward compatibility, but we recommend to update
|
264
|
+
# your elasticsearch to a at least 7.x version and use a single type per index.
|
265
|
+
#
|
266
|
+
# Note that the repository name will be used as the document type.
|
267
|
+
# mapping_default_type
|
268
|
+
bulk_kwargs = { suffix: suffix, type: repo_name, **options }
|
269
|
+
cluster.may_update_type!(bulk_kwargs)
|
211
270
|
|
212
271
|
context ||= {}
|
213
|
-
context[:
|
272
|
+
context[:eager_load_lazy_attributes] = eager_load_lazy_attributes
|
273
|
+
context[:preload_lazy_attributes] = preload_lazy_attributes
|
214
274
|
repo.each_serialized_batch(**context) do |batch|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
275
|
+
bulk(**bulk_kwargs, index: batch)
|
276
|
+
|
277
|
+
if update_lazy_attributes != false
|
278
|
+
attrs = repo.lazy_document_attribute_names(update_lazy_attributes)
|
279
|
+
attrs -= repo.lazy_document_attribute_names(eager_load_lazy_attributes)
|
280
|
+
update_attrs = attrs.each_with_object(Hash.new { |h, k| h[k] = {} }) do |attr_name, memo|
|
281
|
+
filtered_docs = batch.reject do |doc|
|
282
|
+
doc.ignore_on_index? || doc.mutations.key?(attr_name)
|
283
|
+
end
|
284
|
+
next if filtered_docs.empty?
|
285
|
+
|
286
|
+
repo.retrieve_lazy_attribute_values(attr_name, filtered_docs).each do |doc, value|
|
287
|
+
memo[doc.doc_header][attr_name] = value
|
288
|
+
end
|
289
|
+
end
|
290
|
+
if update_attrs.any?
|
291
|
+
bulk_update = update_attrs.map do |header, values|
|
292
|
+
header.merge(data: {doc: values})
|
293
|
+
end
|
294
|
+
bulk(**bulk_kwargs, update: bulk_update)
|
295
|
+
end
|
231
296
|
end
|
232
297
|
|
233
298
|
count += batch.size
|
@@ -236,6 +301,20 @@ module Esse
|
|
236
301
|
count
|
237
302
|
end
|
238
303
|
|
304
|
+
# Update documents by query
|
305
|
+
#
|
306
|
+
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
307
|
+
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
308
|
+
#
|
309
|
+
# @return [Hash] The elasticsearch response hash
|
310
|
+
def update_by_query(suffix: nil, **options)
|
311
|
+
definition = {
|
312
|
+
index: index_name(suffix: suffix),
|
313
|
+
}.merge(options)
|
314
|
+
cluster.may_update_type!(definition)
|
315
|
+
cluster.api.update_by_query(**definition)
|
316
|
+
end
|
317
|
+
|
239
318
|
protected
|
240
319
|
|
241
320
|
def document?(doc)
|
data/lib/esse/index/indices.rb
CHANGED
@@ -26,10 +26,10 @@ module Esse
|
|
26
26
|
#
|
27
27
|
# @see http://www.elasticsearch.org/blog/changing-mapping-with-zero-downtime/
|
28
28
|
# @see Esse::Transport#create_index
|
29
|
-
def create_index(suffix: nil, body: nil, **options)
|
29
|
+
def create_index(suffix: nil, body: nil, settings: nil, **options)
|
30
30
|
options = CREATE_INDEX_RESERVED_KEYWORDS.merge(options)
|
31
31
|
name = build_real_index_name(suffix)
|
32
|
-
definition = body || [settings_hash, mappings_hash].reduce(&:merge)
|
32
|
+
definition = body || [settings_hash(settings: settings), mappings_hash].reduce(&:merge)
|
33
33
|
|
34
34
|
if options.delete(:alias) && name != index_name
|
35
35
|
definition[:aliases] = { index_name => {} }
|
@@ -48,34 +48,40 @@ module Esse
|
|
48
48
|
# @return [Hash] the elasticsearch response
|
49
49
|
#
|
50
50
|
# @see https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html
|
51
|
-
def reset_index(suffix: index_suffix, optimize: true, import: true, reindex: false, **options)
|
51
|
+
def reset_index(suffix: index_suffix, settings: nil, optimize: true, import: true, reindex: false, refresh: nil, **options)
|
52
52
|
cluster.throw_error_when_readonly!
|
53
53
|
|
54
54
|
suffix ||= Esse.timestamp
|
55
55
|
suffix = Esse.timestamp while index_exist?(suffix: suffix)
|
56
56
|
|
57
|
-
if optimize
|
58
|
-
definition = [settings_hash, mappings_hash].reduce(&:merge)
|
57
|
+
if optimize && import
|
58
|
+
definition = [settings_hash(settings: settings), mappings_hash].reduce(&:merge)
|
59
59
|
number_of_replicas = definition.dig(Esse::SETTING_ROOT_KEY, :index, :number_of_replicas)
|
60
60
|
refresh_interval = definition.dig(Esse::SETTING_ROOT_KEY, :index, :refresh_interval)
|
61
61
|
new_number_of_replicas = ((definition[Esse::SETTING_ROOT_KEY] ||= {})[:index] ||= {})[:number_of_replicas] = 0
|
62
62
|
new_refresh_interval = ((definition[Esse::SETTING_ROOT_KEY] ||= {})[:index] ||= {})[:refresh_interval] = '-1'
|
63
63
|
create_index(**options, suffix: suffix, alias: false, body: definition)
|
64
64
|
else
|
65
|
-
create_index(**options, suffix: suffix, alias: false)
|
65
|
+
create_index(**options, suffix: suffix, alias: false, settings: settings)
|
66
66
|
end
|
67
67
|
|
68
68
|
if index_exist? && aliases.none?
|
69
69
|
cluster.api.delete_index(index: index_name)
|
70
70
|
end
|
71
71
|
if import
|
72
|
-
import(
|
73
|
-
|
74
|
-
|
72
|
+
import_kwargs = import.is_a?(Hash) ? import : {}
|
73
|
+
import_kwargs[:refresh] ||= refresh if refresh
|
74
|
+
import(**options, **import_kwargs, suffix: suffix)
|
75
|
+
elsif reindex && (source_indexes = indices_pointing_to_alias).any?
|
76
|
+
reindex_kwargs = reindex.is_a?(Hash) ? reindex : {}
|
77
|
+
reindex_kwargs[:wait_for_completion] = true unless reindex_kwargs.key?(:wait_for_completion)
|
78
|
+
source_indexes.each do |from|
|
79
|
+
cluster.api.reindex(**options, body: { source: { index: from }, dest: { index: index_name(suffix: suffix) } }, refresh: refresh)
|
80
|
+
end
|
75
81
|
end
|
76
82
|
|
77
|
-
if optimize && number_of_replicas != new_number_of_replicas || refresh_interval != new_refresh_interval
|
78
|
-
update_settings(suffix: suffix)
|
83
|
+
if optimize && import && number_of_replicas != new_number_of_replicas || refresh_interval != new_refresh_interval
|
84
|
+
update_settings(suffix: suffix, settings: settings)
|
79
85
|
refresh(suffix: suffix)
|
80
86
|
end
|
81
87
|
|
@@ -152,16 +158,17 @@ module Esse
|
|
152
158
|
#
|
153
159
|
# @param :suffix [String, nil] :suffix The index suffix
|
154
160
|
# @see Esse::Transport#update_settings
|
155
|
-
def update_settings(suffix: nil, **options)
|
161
|
+
def update_settings(suffix: nil, settings: nil, **options)
|
156
162
|
response = nil
|
157
163
|
|
158
|
-
settings = HashUtils.deep_transform_keys(settings_hash.fetch(Esse::SETTING_ROOT_KEY), &:
|
164
|
+
settings = HashUtils.deep_transform_keys(settings_hash(settings: settings).fetch(Esse::SETTING_ROOT_KEY), &:to_sym)
|
159
165
|
if options[:body]
|
160
|
-
|
166
|
+
body = HashUtils.deep_transform_keys(options.delete(:body), &:to_sym)
|
167
|
+
settings = HashUtils.deep_merge(settings, body)
|
161
168
|
end
|
162
|
-
settings.delete(
|
163
|
-
settings[
|
164
|
-
analysis = settings.delete(
|
169
|
+
settings.delete(:number_of_shards) # Can't change number of shards for an index
|
170
|
+
settings[:index]&.delete(:number_of_shards)
|
171
|
+
analysis = settings.delete(:analysis)
|
165
172
|
|
166
173
|
if settings.any?
|
167
174
|
response = cluster.api.update_settings(index: index_name(suffix: suffix), body: settings, **options)
|
@@ -24,7 +24,7 @@ module Esse
|
|
24
24
|
# @return [Enumerator] All serialized entries
|
25
25
|
def documents(repo_name = nil, **kwargs)
|
26
26
|
Enumerator.new do |yielder|
|
27
|
-
each_serialized_batch(repo_name, **kwargs) do |documents
|
27
|
+
each_serialized_batch(repo_name, **kwargs) do |documents|
|
28
28
|
documents.each { |document| yielder.yield(document) }
|
29
29
|
end
|
30
30
|
end
|
data/lib/esse/index/settings.rb
CHANGED
@@ -4,9 +4,28 @@ module Esse
|
|
4
4
|
# https://github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-api/lib/elasticsearch/api/actions/indices/put_settings.rb
|
5
5
|
class Index
|
6
6
|
module ClassMethods
|
7
|
-
|
7
|
+
# Elasticsearch supports passing index.* related settings directly in the body of the request.
|
8
|
+
# We are moving it to the index key to make it more explicit and to be the source-of-truth when merging settings.
|
9
|
+
# So the settings `{ number_of_shards: 1 }` will be transformed to `{ index: { number_of_shards: 1 } }`
|
10
|
+
INDEX_SIMPLIFIED_SETTINGS = %i[
|
11
|
+
number_of_shards
|
12
|
+
number_of_replicas
|
13
|
+
refresh_interval
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
def settings_hash(settings: nil)
|
8
17
|
hash = setting.body
|
9
|
-
|
18
|
+
values = (hash.key?(Esse::SETTING_ROOT_KEY) ? hash[Esse::SETTING_ROOT_KEY] : hash)
|
19
|
+
values = HashUtils.explode_keys(values)
|
20
|
+
if settings.is_a?(Hash)
|
21
|
+
values = HashUtils.deep_merge(values, HashUtils.explode_keys(settings))
|
22
|
+
end
|
23
|
+
INDEX_SIMPLIFIED_SETTINGS.each do |key|
|
24
|
+
next unless values.key?(key)
|
25
|
+
|
26
|
+
(values[:index] ||= {}).merge!(key => values.delete(key))
|
27
|
+
end
|
28
|
+
{ Esse::SETTING_ROOT_KEY => values }
|
10
29
|
end
|
11
30
|
|
12
31
|
# Define /_settings definition by each index.
|
@@ -18,7 +37,7 @@ module Esse
|
|
18
37
|
#
|
19
38
|
# class UserIndex < Esse::Index
|
20
39
|
# settings {
|
21
|
-
# number_of_replicas: 4
|
40
|
+
# index: { number_of_replicas: 4 }
|
22
41
|
# }
|
23
42
|
# end
|
24
43
|
#
|
@@ -2,11 +2,19 @@
|
|
2
2
|
|
3
3
|
module Esse
|
4
4
|
class LazyDocumentHeader
|
5
|
+
ACCEPTABLE_CLASSES = [Esse::LazyDocumentHeader, Esse::Document].freeze
|
6
|
+
ACCEPTABLE_DOC_TYPES = [nil, '_doc', 'doc'].freeze
|
7
|
+
|
5
8
|
def self.coerce_each(values)
|
9
|
+
values = Esse::ArrayUtils.wrap(values)
|
10
|
+
return values if values.all? do |value|
|
11
|
+
ACCEPTABLE_CLASSES.any? { |klass| value.is_a?(klass) }
|
12
|
+
end
|
13
|
+
|
6
14
|
arr = []
|
7
|
-
|
15
|
+
values.flatten.map do |value|
|
8
16
|
instance = coerce(value)
|
9
|
-
arr << instance if instance
|
17
|
+
arr << instance if instance && !instance.id.nil?
|
10
18
|
end
|
11
19
|
arr
|
12
20
|
end
|
@@ -17,57 +25,61 @@ module Esse
|
|
17
25
|
if value.is_a?(Esse::LazyDocumentHeader)
|
18
26
|
value
|
19
27
|
elsif value.is_a?(Esse::Document)
|
20
|
-
|
28
|
+
value
|
21
29
|
elsif value.is_a?(Hash)
|
22
30
|
resp = value.transform_keys do |key|
|
23
31
|
case key
|
24
32
|
when :_id, :id, '_id', 'id'
|
25
|
-
:
|
33
|
+
:id
|
26
34
|
when :_routing, :routing, '_routing', 'routing'
|
27
35
|
:routing
|
28
36
|
when :_type, :type, '_type', 'type'
|
29
|
-
:
|
37
|
+
:type
|
30
38
|
else
|
31
39
|
key.to_sym
|
32
40
|
end
|
33
41
|
end
|
34
|
-
|
42
|
+
resp[:id] ||= nil
|
43
|
+
new(**resp)
|
35
44
|
elsif String === value || Integer === value
|
36
|
-
new(
|
45
|
+
new(id: value)
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
40
|
-
|
41
|
-
@attributes = attributes
|
42
|
-
end
|
49
|
+
attr_reader :id, :type, :routing, :options
|
43
50
|
|
44
|
-
def
|
45
|
-
|
51
|
+
def initialize(id:, type: nil, routing: nil, **extra_attributes)
|
52
|
+
@id = id
|
53
|
+
@type = type
|
54
|
+
@routing = routing
|
55
|
+
@options = extra_attributes.freeze
|
46
56
|
end
|
47
57
|
|
48
58
|
def to_h
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@attributes.fetch(:_id)
|
54
|
-
end
|
55
|
-
|
56
|
-
def type
|
57
|
-
@attributes[:_type]
|
59
|
+
options.merge(_id: id).tap do |hash|
|
60
|
+
hash[:_type] = type if type
|
61
|
+
hash[:routing] = routing if routing
|
62
|
+
end
|
58
63
|
end
|
59
64
|
|
60
|
-
def
|
61
|
-
|
65
|
+
def document_for_partial_update(source)
|
66
|
+
Esse::DocumentForPartialUpdate.new(self, source: source)
|
62
67
|
end
|
63
68
|
|
64
|
-
def
|
65
|
-
|
69
|
+
def doc_header
|
70
|
+
{ _id: id }.tap do |hash|
|
71
|
+
hash[:_type] = type if type
|
72
|
+
hash[:routing] = routing if routing
|
73
|
+
end
|
66
74
|
end
|
67
75
|
|
68
|
-
def eql?(other)
|
69
|
-
|
76
|
+
def eql?(other, **)
|
77
|
+
ACCEPTABLE_CLASSES.any? { |klass| other.is_a?(klass) } &&
|
78
|
+
id.to_s == other.id.to_s &&
|
79
|
+
routing == other.routing &&
|
80
|
+
((ACCEPTABLE_DOC_TYPES.include?(type) && ACCEPTABLE_DOC_TYPES.include?(other.type)) || type == other.type)
|
70
81
|
end
|
71
82
|
alias_method :==, :eql?
|
72
83
|
end
|
73
84
|
end
|
85
|
+
|
@@ -47,5 +47,15 @@ module Esse
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
def explode_keys(hash, separator = '.')
|
52
|
+
hash.each_with_object({}) do |(key, value), result|
|
53
|
+
is_symbol = key.is_a?(Symbol)
|
54
|
+
keys = key.to_s.split(separator)
|
55
|
+
last_key = keys.pop
|
56
|
+
current = keys.reduce(result) { |memo, k| memo[is_symbol ? k.to_sym : k] ||= {} }
|
57
|
+
current[is_symbol ? last_key.to_sym : last_key] = value
|
58
|
+
end
|
59
|
+
end
|
50
60
|
end
|
51
61
|
end
|
@@ -16,7 +16,7 @@ module Esse
|
|
16
16
|
|
17
17
|
def documents_for_lazy_attribute(name, ids_or_doc_headers)
|
18
18
|
retrieve_lazy_attribute_values(name, ids_or_doc_headers).map do |doc_header, datum|
|
19
|
-
doc_header.
|
19
|
+
doc_header.document_for_partial_update(name => datum)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -36,11 +36,10 @@ module Esse
|
|
36
36
|
return [] unless result.is_a?(Hash)
|
37
37
|
|
38
38
|
result.each_with_object({}) do |(key, value), memo|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
39
|
+
val = docs.find { |doc| doc.eql?(key, match_lazy_doc_header: true) || doc.id == key }
|
40
|
+
next unless val
|
41
|
+
|
42
|
+
memo[val] = value
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
@@ -69,27 +69,65 @@ module Esse
|
|
69
69
|
@collection_proc = collection_klass || block
|
70
70
|
end
|
71
71
|
|
72
|
+
# Expose the collection class to let external plugins and extensions to access it.
|
73
|
+
# @return [Class, nil] The collection class
|
74
|
+
# IDEA: When collection is defined as a block, it should setup a class with the block content.
|
75
|
+
def collection_class
|
76
|
+
return unless @collection_proc.is_a?(Class)
|
77
|
+
|
78
|
+
@collection_proc
|
79
|
+
end
|
80
|
+
|
72
81
|
# Wrap collection data into serialized batches
|
73
82
|
#
|
74
83
|
# @param [Hash] kwargs The context
|
75
84
|
# @return [Enumerator] The enumerator
|
76
85
|
# @yield [Array, **context] serialized collection and the optional context from the collection
|
77
|
-
def each_serialized_batch(
|
86
|
+
def each_serialized_batch(eager_load_lazy_attributes: false, preload_lazy_attributes: false, **kwargs)
|
87
|
+
if kwargs.key?(:lazy_attributes)
|
88
|
+
warn 'The `lazy_attributes` option is deprecated. Use `eager_load_lazy_attributes` instead.'
|
89
|
+
eager_load_lazy_attributes = kwargs.delete(:lazy_attributes)
|
90
|
+
end
|
91
|
+
|
92
|
+
lazy_attrs_to_eager_load = lazy_document_attribute_names(eager_load_lazy_attributes)
|
93
|
+
lazy_attrs_to_search_preload = lazy_document_attribute_names(preload_lazy_attributes)
|
94
|
+
lazy_attrs_to_search_preload -= lazy_attrs_to_eager_load
|
95
|
+
|
78
96
|
each_batch(**kwargs) do |*args|
|
79
97
|
batch, collection_context = args
|
80
98
|
collection_context ||= {}
|
81
99
|
entries = [*batch].map { |entry| serialize(entry, **collection_context) }.compact
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
100
|
+
lazy_attrs_to_eager_load.each do |attr_name|
|
101
|
+
retrieve_lazy_attribute_values(attr_name, entries).each do |doc_header, value|
|
102
|
+
doc = entries.find { |d| d.eql?(doc_header, match_lazy_doc_header: true) }
|
103
|
+
doc&.mutate(attr_name) { value }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if lazy_attrs_to_search_preload.any?
|
108
|
+
entries.group_by(&:routing).each do |routing, docs|
|
109
|
+
search_request = {
|
110
|
+
query: { ids: { values: docs.map(&:id) } },
|
111
|
+
size: docs.size,
|
112
|
+
_source: lazy_attrs_to_search_preload
|
113
|
+
}
|
114
|
+
search_request[:routing] = routing if routing
|
115
|
+
index.search(**search_request).response.hits.each do |hit|
|
116
|
+
header = [hit['_id'], hit['_routing'], hit['_type']]
|
117
|
+
next if header[0].nil?
|
118
|
+
|
119
|
+
hit.dig('_source')&.each do |attr_name, attr_value|
|
120
|
+
real_attr_name = lazy_document_attribute_names(attr_name).first
|
121
|
+
next if real_attr_name.nil?
|
122
|
+
|
123
|
+
doc = entries.find { |d| Esse.document_match_with_header?(d, *header) }
|
124
|
+
doc&.mutate(real_attr_name) { attr_value }
|
125
|
+
end
|
88
126
|
end
|
89
127
|
end
|
90
128
|
end
|
91
129
|
|
92
|
-
yield entries
|
130
|
+
yield entries
|
93
131
|
end
|
94
132
|
end
|
95
133
|
|
@@ -101,7 +139,7 @@ module Esse
|
|
101
139
|
# @return [Enumerator] All serialized entries
|
102
140
|
def documents(**kwargs)
|
103
141
|
Enumerator.new do |yielder|
|
104
|
-
each_serialized_batch(**kwargs) do |docs
|
142
|
+
each_serialized_batch(**kwargs) do |docs|
|
105
143
|
docs.each { |document| yielder.yield(document) }
|
106
144
|
end
|
107
145
|
end
|
@@ -185,6 +185,83 @@ module Esse
|
|
185
185
|
payload[:response] = coerce_exception { client.indices.put_settings(**opts) }
|
186
186
|
end
|
187
187
|
end
|
188
|
+
|
189
|
+
# Allows to copy documents from one index to another, optionally filtering the source
|
190
|
+
# documents by a query, changing the destination index settings, or fetching the
|
191
|
+
# documents from a remote cluster.
|
192
|
+
#
|
193
|
+
# @option arguments [Boolean] :refresh Should the affected indexes be refreshed?
|
194
|
+
# @option arguments [Time] :timeout Time each individual bulk request should wait for shards that are unavailable.
|
195
|
+
# @option arguments [String] :wait_for_active_shards Sets the number of shard copies that must be active before proceeding with the reindex operation. Defaults to 1, meaning the primary shard only. Set to `all` for all shard copies, otherwise set to any non-negative value less than or equal to the total number of copies for the shard (number of replicas + 1)
|
196
|
+
# @option arguments [Boolean] :wait_for_completion Should the request should block until the reindex is complete.
|
197
|
+
# @option arguments [Number] :requests_per_second The throttle to set on this request in sub-requests per second. -1 means no throttle.
|
198
|
+
# @option arguments [Time] :scroll Control how long to keep the search context alive
|
199
|
+
# @option arguments [Number|string] :slices The number of slices this task should be divided into. Defaults to 1, meaning the task isn't sliced into subtasks. Can be set to `auto`.
|
200
|
+
# @option arguments [Number] :max_docs Maximum number of documents to process (default: all documents)
|
201
|
+
# @option arguments [Hash] :headers Custom HTTP headers
|
202
|
+
# @option arguments [Hash] :body The search definition using the Query DSL and the prototype for the index request. (*Required*)
|
203
|
+
#
|
204
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html
|
205
|
+
def reindex(body:, **options)
|
206
|
+
throw_error_when_readonly!
|
207
|
+
|
208
|
+
Esse::Events.instrument('elasticsearch.reindex') do |payload|
|
209
|
+
payload[:request] = opts = options.merge(body: body)
|
210
|
+
payload[:response] = coerce_exception { client.reindex(**opts) }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Performs an update on every document in the index without changing the source,
|
215
|
+
# for example to pick up a mapping change.
|
216
|
+
#
|
217
|
+
# @option arguments [List] :index A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices (*Required*)
|
218
|
+
# @option arguments [String] :analyzer The analyzer to use for the query string
|
219
|
+
# @option arguments [Boolean] :analyze_wildcard Specify whether wildcard and prefix queries should be analyzed (default: false)
|
220
|
+
# @option arguments [String] :default_operator The default operator for query string query (AND or OR) (options: AND, OR)
|
221
|
+
# @option arguments [String] :df The field to use as default where no field prefix is given in the query string
|
222
|
+
# @option arguments [Number] :from Starting offset (default: 0)
|
223
|
+
# @option arguments [Boolean] :ignore_unavailable Whether specified concrete indices should be ignored when unavailable (missing or closed)
|
224
|
+
# @option arguments [Boolean] :allow_no_indices Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
|
225
|
+
# @option arguments [String] :conflicts What to do when the update by query hits version conflicts? (options: abort, proceed)
|
226
|
+
# @option arguments [String] :expand_wildcards Whether to expand wildcard expression to concrete indices that are open, closed or both. (options: open, closed, hidden, none, all)
|
227
|
+
# @option arguments [Boolean] :lenient Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
|
228
|
+
# @option arguments [String] :pipeline Ingest pipeline to set on index requests made by this action. (default: none)
|
229
|
+
# @option arguments [String] :preference Specify the node or shard the operation should be performed on (default: random)
|
230
|
+
# @option arguments [String] :q Query in the Lucene query string syntax
|
231
|
+
# @option arguments [List] :routing A comma-separated list of specific routing values
|
232
|
+
# @option arguments [Time] :scroll Specify how long a consistent view of the index should be maintained for scrolled search
|
233
|
+
# @option arguments [String] :search_type Search operation type (options: query_then_fetch, dfs_query_then_fetch)
|
234
|
+
# @option arguments [Time] :search_timeout Explicit timeout for each search request. Defaults to no timeout.
|
235
|
+
# @option arguments [Number] :size Deprecated, please use `max_docs` instead
|
236
|
+
# @option arguments [Number] :max_docs Maximum number of documents to process (default: all documents)
|
237
|
+
# @option arguments [List] :sort A comma-separated list of <field>:<direction> pairs
|
238
|
+
# @option arguments [List] :_source True or false to return the _source field or not, or a list of fields to return
|
239
|
+
# @option arguments [List] :_source_excludes A list of fields to exclude from the returned _source field
|
240
|
+
# @option arguments [List] :_source_includes A list of fields to extract and return from the _source field
|
241
|
+
# @option arguments [Number] :terminate_after The maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early.
|
242
|
+
# @option arguments [List] :stats Specific 'tag' of the request for logging and statistical purposes
|
243
|
+
# @option arguments [Boolean] :version Specify whether to return document version as part of a hit
|
244
|
+
# @option arguments [Boolean] :version_type Should the document increment the version number (internal) on hit or not (reindex)
|
245
|
+
# @option arguments [Boolean] :request_cache Specify if request cache should be used for this request or not, defaults to index level setting
|
246
|
+
# @option arguments [Boolean] :refresh Should the affected indexes be refreshed?
|
247
|
+
# @option arguments [Time] :timeout Time each individual bulk request should wait for shards that are unavailable.
|
248
|
+
# @option arguments [String] :wait_for_active_shards Sets the number of shard copies that must be active before proceeding with the update by query operation. Defaults to 1, meaning the primary shard only. Set to `all` for all shard copies, otherwise set to any non-negative value less than or equal to the total number of copies for the shard (number of replicas + 1)
|
249
|
+
# @option arguments [Number] :scroll_size Size on the scroll request powering the update by query
|
250
|
+
# @option arguments [Boolean] :wait_for_completion Should the request should block until the update by query operation is complete.
|
251
|
+
# @option arguments [Number] :requests_per_second The throttle to set on this request in sub-requests per second. -1 means no throttle.
|
252
|
+
# @option arguments [Number|string] :slices The number of slices this task should be divided into. Defaults to 1, meaning the task isn't sliced into subtasks. Can be set to `auto`.
|
253
|
+
# @option arguments [Hash] :headers Custom HTTP headers
|
254
|
+
# @option arguments [Hash] :body The search definition using the Query DSL
|
255
|
+
#
|
256
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html
|
257
|
+
def update_by_query(index:, **options)
|
258
|
+
throw_error_when_readonly!
|
259
|
+
|
260
|
+
Esse::Events.instrument('elasticsearch.update_by_query') do |payload|
|
261
|
+
payload[:request] = opts = options.merge(index: index)
|
262
|
+
payload[:response] = coerce_exception { client.update_by_query(**opts) }
|
263
|
+
end
|
264
|
+
end
|
188
265
|
end
|
189
266
|
|
190
267
|
include InstanceMethods
|
data/lib/esse/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: esse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcos G. Zimmermann
|
8
8
|
autorequire:
|
9
9
|
bindir: exec
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -248,6 +248,7 @@ files:
|
|
248
248
|
- lib/esse/deprecations/repository_backend_delegator.rb
|
249
249
|
- lib/esse/deprecations/serializer.rb
|
250
250
|
- lib/esse/document.rb
|
251
|
+
- lib/esse/document_for_partial_update.rb
|
251
252
|
- lib/esse/document_lazy_attribute.rb
|
252
253
|
- lib/esse/dynamic_template.rb
|
253
254
|
- lib/esse/errors.rb
|
@@ -318,9 +319,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
318
319
|
version: 2.3.0
|
319
320
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
320
321
|
requirements:
|
321
|
-
- - "
|
322
|
+
- - ">"
|
322
323
|
- !ruby/object:Gem::Version
|
323
|
-
version:
|
324
|
+
version: 1.3.1
|
324
325
|
requirements: []
|
325
326
|
rubygems_version: 3.0.3.1
|
326
327
|
signing_key:
|