esse 0.3.5 → 0.4.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/esse/cli/index.rb +8 -9
- data/lib/esse/core.rb +7 -0
- data/lib/esse/document.rb +19 -6
- data/lib/esse/document_for_partial_update.rb +16 -0
- data/lib/esse/import/bulk.rb +17 -13
- data/lib/esse/index/documents.rb +92 -27
- data/lib/esse/index/indices.rb +3 -1
- data/lib/esse/index/object_document_mapper.rb +1 -1
- data/lib/esse/lazy_document_header.rb +39 -27
- data/lib/esse/repository/documents.rb +5 -6
- data/lib/esse/repository/object_document_mapper.rb +47 -9
- 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
|
data/lib/esse/cli/index.rb
CHANGED
@@ -97,18 +97,17 @@ module Esse
|
|
97
97
|
option :suffix, type: :string, default: nil, aliases: '-s', desc: 'Suffix to append to index name'
|
98
98
|
option :context, type: :hash, default: {}, required: true, desc: 'List of options to pass to the index class'
|
99
99
|
option :repo, type: :string, default: nil, alias: '-r', desc: 'Repository to use for import'
|
100
|
-
option :
|
101
|
-
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
|
+
|
102
104
|
def import(*index_classes)
|
103
105
|
require_relative 'index/import'
|
104
106
|
opts = HashUtils.deep_transform_keys(options.to_h, &:to_sym)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
if (val = opts[:lazy_update_document_attributes])
|
111
|
-
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
|
112
111
|
end
|
113
112
|
Import.new(indices: index_classes, **opts).run
|
114
113
|
end
|
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,6 +104,10 @@ 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)
|
@@ -115,7 +126,9 @@ module Esse
|
|
115
126
|
instance_variable_set(:@__mutated_source__, nil)
|
116
127
|
end
|
117
128
|
|
118
|
-
|
129
|
+
def mutations
|
130
|
+
@__mutations__ || MUTATIONS_FALLBACK
|
131
|
+
end
|
119
132
|
|
120
133
|
def mutated_source
|
121
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/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
|
-
# This gem supports multiple types per index for backward compatibility, but we recommend to update
|
217
|
-
# your elasticsearch to a at least 7.x version and use a single type per index.
|
218
|
-
#
|
219
|
-
# Note that the repository name will be used as the document type.
|
220
|
-
# mapping_default_type
|
221
|
-
kwargs = { suffix: suffix, type: repo_name, **options }
|
222
|
-
cluster.may_update_type!(kwargs)
|
223
|
-
|
224
|
-
bulk(**kwargs, index: batch)
|
275
|
+
bulk(**bulk_kwargs, index: batch)
|
225
276
|
|
226
|
-
|
227
|
-
|
228
|
-
|
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?
|
229
285
|
|
230
|
-
|
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
|
data/lib/esse/index/indices.rb
CHANGED
@@ -69,7 +69,9 @@ module Esse
|
|
69
69
|
cluster.api.delete_index(index: index_name)
|
70
70
|
end
|
71
71
|
if import
|
72
|
-
import(
|
72
|
+
import_kwargs = import.is_a?(Hash) ? import : {}
|
73
|
+
import_kwargs[:refresh] ||= refresh if refresh
|
74
|
+
import(**options, **import_kwargs, suffix: suffix)
|
73
75
|
elsif reindex && (source_indexes = indices_pointing_to_alias).any?
|
74
76
|
reindex_kwargs = reindex.is_a?(Hash) ? reindex : {}
|
75
77
|
reindex_kwargs[:wait_for_completion] = true unless reindex_kwargs.key?(:wait_for_completion)
|
@@ -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
|
@@ -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
|
+
|
@@ -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
|
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-08-
|
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:
|