esse 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/esse/backend/index/aliases.rb +8 -8
- data/lib/esse/backend/index/close.rb +3 -3
- data/lib/esse/backend/index/create.rb +4 -4
- data/lib/esse/backend/index/delete.rb +4 -4
- data/lib/esse/backend/index/documents.rb +253 -6
- data/lib/esse/backend/index/existance.rb +3 -3
- data/lib/esse/backend/index/open.rb +3 -3
- data/lib/esse/backend/index/refresh.rb +7 -5
- data/lib/esse/backend/index/reset.rb +4 -4
- data/lib/esse/backend/index/update.rb +7 -7
- data/lib/esse/backend/index.rb +16 -14
- data/lib/esse/backend/repository_backend.rb +105 -0
- data/lib/esse/cli/event_listener.rb +14 -0
- data/lib/esse/cli/generate.rb +53 -12
- data/lib/esse/cli/index/base_operation.rb +5 -13
- data/lib/esse/cli/index/import.rb +6 -2
- data/lib/esse/cli/index/update_mapping.rb +3 -4
- data/lib/esse/cli/index.rb +2 -0
- data/lib/esse/cli/templates/{type_collection.rb.erb → collection.rb.erb} +6 -18
- data/lib/esse/cli/templates/config.rb.erb +13 -3
- data/lib/esse/cli/templates/index.rb.erb +53 -109
- data/lib/esse/cli/templates/mappings.json +27 -0
- data/lib/esse/cli/templates/serializer.rb.erb +34 -0
- data/lib/esse/cli/templates/settings.json +62 -0
- data/lib/esse/client_proxy/search.rb +44 -0
- data/lib/esse/client_proxy.rb +32 -0
- data/lib/esse/cluster.rb +64 -9
- data/lib/esse/cluster_engine.rb +42 -0
- data/lib/esse/collection.rb +18 -0
- data/lib/esse/config.rb +14 -2
- data/lib/esse/core.rb +23 -6
- data/lib/esse/deprecations/cluster.rb +27 -0
- data/lib/esse/deprecations/index.rb +19 -0
- data/lib/esse/deprecations/repository.rb +19 -0
- data/lib/esse/deprecations.rb +3 -0
- data/lib/esse/dynamic_template.rb +39 -0
- data/lib/esse/errors.rb +53 -2
- data/lib/esse/events/event.rb +4 -19
- data/lib/esse/events.rb +3 -0
- data/lib/esse/hash_document.rb +38 -0
- data/lib/esse/import/bulk.rb +96 -0
- data/lib/esse/import/request_body.rb +60 -0
- data/lib/esse/index/attributes.rb +98 -0
- data/lib/esse/index/base.rb +1 -1
- data/lib/esse/index/inheritance.rb +30 -0
- data/lib/esse/index/mappings.rb +6 -19
- data/lib/esse/index/object_document_mapper.rb +95 -0
- data/lib/esse/index/plugins.rb +42 -0
- data/lib/esse/index/search.rb +27 -0
- data/lib/esse/index/settings.rb +2 -2
- data/lib/esse/index/type.rb +52 -11
- data/lib/esse/index.rb +10 -6
- data/lib/esse/index_mapping.rb +10 -2
- data/lib/esse/index_setting.rb +3 -1
- data/lib/esse/null_document.rb +35 -0
- data/lib/esse/plugins.rb +12 -0
- data/lib/esse/primitives/hstring.rb +1 -1
- data/lib/esse/{index_type → repository}/actions.rb +1 -1
- data/lib/esse/{index_type → repository}/backend.rb +2 -2
- data/lib/esse/repository/object_document_mapper.rb +157 -0
- data/lib/esse/repository.rb +18 -0
- data/lib/esse/search/query.rb +105 -0
- data/lib/esse/search/response.rb +46 -0
- data/lib/esse/serializer.rb +76 -0
- data/lib/esse/version.rb +1 -1
- data/lib/esse.rb +20 -5
- metadata +35 -30
- data/lib/esse/backend/index_type/documents.rb +0 -214
- data/lib/esse/backend/index_type.rb +0 -37
- data/lib/esse/cli/templates/type_mappings.json +0 -6
- data/lib/esse/cli/templates/type_serializer.rb.erb +0 -23
- data/lib/esse/index/naming.rb +0 -64
- data/lib/esse/index_type/mappings.rb +0 -42
- data/lib/esse/index_type.rb +0 -15
- data/lib/esse/object_document_mapper.rb +0 -110
@@ -1,214 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Esse
|
4
|
-
module Backend
|
5
|
-
class IndexType
|
6
|
-
module InstanceMethods
|
7
|
-
# Resolve collection and index data
|
8
|
-
#
|
9
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
10
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
11
|
-
# @option [Hash] :context The collection context. This value will be passed as argument to the collection
|
12
|
-
# May be SQL condition or any other filter you have defined on the collection.
|
13
|
-
def import(context: {}, suffix: nil, **options)
|
14
|
-
each_serialized_batch(**(context || {})) do |batch|
|
15
|
-
bulk(index: batch, suffix: suffix, **options)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
alias_method :import!, :import
|
19
|
-
|
20
|
-
# Performs multiple indexing or delete operations in a single API call.
|
21
|
-
# This reduces overhead and can greatly increase indexing speed.
|
22
|
-
#
|
23
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
24
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
25
|
-
# @option [Array] :index list of serialized documents to be indexed(Optional)
|
26
|
-
# @option [Array] :delete list of serialized documents to be deleted(Optional)
|
27
|
-
# @option [Array] :create list of serialized documents to be created(Optional)
|
28
|
-
# @return [Hash, nil] the elasticsearch response or nil if there is no data.
|
29
|
-
#
|
30
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-bulk.html
|
31
|
-
def bulk(index: nil, delete: nil, create: nil, suffix: nil, **options)
|
32
|
-
body = []
|
33
|
-
Array(index).each do |entry|
|
34
|
-
id, data = Esse.doc_id!(entry)
|
35
|
-
body << { index: { _id: id, data: data } } if id
|
36
|
-
end
|
37
|
-
Array(create).each do |entry|
|
38
|
-
id, data = Esse.doc_id!(entry)
|
39
|
-
body << { create: { _id: id, data: data } } if id
|
40
|
-
end
|
41
|
-
Array(delete).each do |entry|
|
42
|
-
id, _data = Esse.doc_id!(entry, delete: [], keep: %w[_id id])
|
43
|
-
body << { delete: { _id: id } } if id
|
44
|
-
end
|
45
|
-
|
46
|
-
return if body.empty?
|
47
|
-
|
48
|
-
definition = {
|
49
|
-
index: index_name(suffix: suffix),
|
50
|
-
type: type_name,
|
51
|
-
body: body,
|
52
|
-
}.merge(options)
|
53
|
-
|
54
|
-
client.bulk(definition)
|
55
|
-
end
|
56
|
-
alias_method :bulk!, :bulk
|
57
|
-
|
58
|
-
# Adds a JSON document to the specified index and makes it searchable. If the document
|
59
|
-
# already exists, updates the document and increments its version.
|
60
|
-
#
|
61
|
-
# UsersIndex::User.index(id: 1, body: { name: 'name' }) # { '_id' => 1, ...}
|
62
|
-
#
|
63
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
64
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
65
|
-
# @option [Hash] :body The JSON document that will be indexed (Required)
|
66
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
67
|
-
# @return [Hash] the elasticsearch response Hash
|
68
|
-
#
|
69
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-index_.html
|
70
|
-
def index(id:, body:, suffix: nil, **options)
|
71
|
-
client.index(
|
72
|
-
index: index_name(suffix: suffix), type: type_name, id: id, body: body, **options
|
73
|
-
)
|
74
|
-
end
|
75
|
-
alias_method :index!, :index
|
76
|
-
|
77
|
-
# Updates a document using the specified script.
|
78
|
-
#
|
79
|
-
# UsersIndex::User.update!(id: 1, body: { doc: { ... } }) # { '_id' => 1, ...}
|
80
|
-
#
|
81
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
82
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
83
|
-
# @option [Hash] :body the body of the request
|
84
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
85
|
-
# @raise [Elasticsearch::Transport::Transport::Errors::NotFound] when the doc does not exist
|
86
|
-
# @return [Hash] elasticsearch response hash
|
87
|
-
#
|
88
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-update.html
|
89
|
-
def update!(id:, body:, suffix: nil, **options)
|
90
|
-
client.update(
|
91
|
-
index: index_name(suffix: suffix), type: type_name, id: id, body: body, **options
|
92
|
-
)
|
93
|
-
end
|
94
|
-
|
95
|
-
# Updates a document using the specified script.
|
96
|
-
#
|
97
|
-
# UsersIndex::User.update(id: 1, body: { doc: { ... } }) # { '_id' => 1, ...}
|
98
|
-
#
|
99
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
100
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
101
|
-
# @option [Hash] :body the body of the request
|
102
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
103
|
-
# @return [Hash] the elasticsearch response, or an hash with 'errors' as true in case of failure
|
104
|
-
#
|
105
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-update.html
|
106
|
-
def update(id:, body:, suffix: nil, **options)
|
107
|
-
update!(id: id, body: body, suffix: suffix, **options)
|
108
|
-
rescue Elasticsearch::Transport::Transport::Errors::NotFound
|
109
|
-
{ 'errors' => true }
|
110
|
-
end
|
111
|
-
|
112
|
-
# Removes a JSON document from the specified index.
|
113
|
-
#
|
114
|
-
# UsersIndex::User.delete!(id: 1) # true
|
115
|
-
# UsersIndex::User.delete!(id: 'missing') # raise Elasticsearch::Transport::Transport::Errors::NotFound
|
116
|
-
#
|
117
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
118
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
119
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
120
|
-
# @raise [Elasticsearch::Transport::Transport::Errors::NotFound] when the doc does not exist
|
121
|
-
# @return [Boolean] true when the operation is successfully completed
|
122
|
-
#
|
123
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-delete.html
|
124
|
-
def delete!(id:, suffix: nil, **options)
|
125
|
-
client.delete(options.merge(index: index_name(suffix: suffix), type: type_name, id: id))
|
126
|
-
end
|
127
|
-
|
128
|
-
# Removes a JSON document from the specified index.
|
129
|
-
#
|
130
|
-
# UsersIndex::User.delete(id: 1) # true
|
131
|
-
# UsersIndex::User.delete(id: 'missing') # false
|
132
|
-
#
|
133
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
134
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
135
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
136
|
-
# @raise [Elasticsearch::Transport::Transport::Errors::NotFound] when the doc does not exist
|
137
|
-
# @return [Boolean] true when the operation is successfully completed
|
138
|
-
#
|
139
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-delete.html
|
140
|
-
def delete(id:, suffix: nil, **options)
|
141
|
-
delete!(id: id, suffix: suffix, **options)
|
142
|
-
rescue Elasticsearch::Transport::Transport::Errors::NotFound
|
143
|
-
false
|
144
|
-
end
|
145
|
-
|
146
|
-
# Gets the number of matches for a search query.
|
147
|
-
#
|
148
|
-
# UsersIndex::User.count # 999
|
149
|
-
# UsersIndex::User.count(body: { ... }) # 32
|
150
|
-
#
|
151
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
152
|
-
# @option [Hash] :body A query to restrict the results specified with the Query DSL (optional)
|
153
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
154
|
-
# @return [Integer] amount of documents found
|
155
|
-
#
|
156
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/search-count.html
|
157
|
-
def count(suffix: nil, **options)
|
158
|
-
response = client.count(options.merge(index: index_name(suffix: suffix), type: type_name))
|
159
|
-
response['count']
|
160
|
-
rescue Elasticsearch::Transport::Transport::Errors::NotFound
|
161
|
-
0
|
162
|
-
end
|
163
|
-
|
164
|
-
# Check if a JSON document exists
|
165
|
-
#
|
166
|
-
# UsersIndex::User.exist?(id: 1) # true
|
167
|
-
# UsersIndex::User.exist?(id: 'missing') # false
|
168
|
-
#
|
169
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
170
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
171
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
172
|
-
# @return [Boolean] true if the document exists
|
173
|
-
def exist?(id:, suffix: nil, **options)
|
174
|
-
client.exists(options.merge(index: index_name(suffix: suffix), type: type_name, id: id))
|
175
|
-
end
|
176
|
-
|
177
|
-
# Retrieves the specified JSON document from an index.
|
178
|
-
#
|
179
|
-
# UsersIndex::User.find!(id: 1) # { '_id' => 1, ... }
|
180
|
-
# UsersIndex::User.find!(id: 'missing') # raise Elasticsearch::Transport::Transport::Errors::NotFound
|
181
|
-
#
|
182
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
183
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
184
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
185
|
-
# @raise [Elasticsearch::Transport::Transport::Errors::NotFound] when the doc does not exist
|
186
|
-
# @return [Hash] The elasticsearch document.
|
187
|
-
#
|
188
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-get.html
|
189
|
-
def find!(id:, suffix: nil, **options)
|
190
|
-
client.get(options.merge(index: index_name(suffix: suffix), type: type_name, id: id))
|
191
|
-
end
|
192
|
-
|
193
|
-
# Retrieves the specified JSON document from an index.
|
194
|
-
#
|
195
|
-
# UsersIndex::User.find(id: 1) # { '_id' => 1, ... }
|
196
|
-
# UsersIndex::User.find(id: 'missing') # nil
|
197
|
-
#
|
198
|
-
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
199
|
-
# @option [String, Integer] :id The `_id` of the elasticsearch document
|
200
|
-
# @option [String, nil] :suffix The index suffix. Defaults to the nil.
|
201
|
-
# @return [Hash, nil] The elasticsearch document
|
202
|
-
#
|
203
|
-
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docs-get.html
|
204
|
-
def find(id:, suffix: nil, **options)
|
205
|
-
find!(id: id, suffix: suffix, **options)
|
206
|
-
rescue Elasticsearch::Transport::Transport::Errors::NotFound
|
207
|
-
nil
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
include InstanceMethods
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'forwardable'
|
4
|
-
|
5
|
-
module Esse
|
6
|
-
module Backend
|
7
|
-
class IndexType
|
8
|
-
require_relative 'index_type/documents'
|
9
|
-
|
10
|
-
extend Forwardable
|
11
|
-
|
12
|
-
# Type delegators
|
13
|
-
def_delegators :@index_type, :type_name, :each_serialized_batch, :serialize
|
14
|
-
|
15
|
-
def initialize(type)
|
16
|
-
@index_type = type
|
17
|
-
end
|
18
|
-
|
19
|
-
protected
|
20
|
-
|
21
|
-
def index_name(suffix: nil)
|
22
|
-
suffix = Hstring.new(suffix).underscore.presence
|
23
|
-
return index_class.index_name unless suffix
|
24
|
-
|
25
|
-
[index_class.index_name, suffix].join('_')
|
26
|
-
end
|
27
|
-
|
28
|
-
def index_class
|
29
|
-
@index_type.index
|
30
|
-
end
|
31
|
-
|
32
|
-
def client
|
33
|
-
index_class.cluster.client
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class <%= @index_name %> < <%= @base_class %>
|
4
|
-
module Serializers
|
5
|
-
class <%= @type.camelize %>Serializer
|
6
|
-
def initialize(<%= @type %>, **params)
|
7
|
-
@entity = <%= @type %>
|
8
|
-
@params = params
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_h
|
12
|
-
{
|
13
|
-
id: entity.id, # This field is required
|
14
|
-
name: entity.name,
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
|
-
protected
|
19
|
-
|
20
|
-
attr_reader :entity, :params
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/esse/index/naming.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Esse
|
4
|
-
class Index
|
5
|
-
module ClassMethods
|
6
|
-
TEMPLATE_DIRS = [
|
7
|
-
'%<dirname>s/templates',
|
8
|
-
'%<dirname>s'
|
9
|
-
].freeze
|
10
|
-
|
11
|
-
def index_name=(value)
|
12
|
-
@index_name = index_prefixed_name(value)
|
13
|
-
end
|
14
|
-
|
15
|
-
def index_name
|
16
|
-
@index_name || index_prefixed_name(normalized_name)
|
17
|
-
end
|
18
|
-
|
19
|
-
def index_name?
|
20
|
-
!index_name.nil?
|
21
|
-
end
|
22
|
-
|
23
|
-
def index_version=(value)
|
24
|
-
@index_version = Hstring.new(value.to_s).underscore.presence
|
25
|
-
end
|
26
|
-
|
27
|
-
def index_version
|
28
|
-
@index_version
|
29
|
-
end
|
30
|
-
|
31
|
-
def uname
|
32
|
-
Hstring.new(name).underscore.presence
|
33
|
-
end
|
34
|
-
|
35
|
-
def index_directory
|
36
|
-
return unless uname
|
37
|
-
return if uname == 'Esse::Index'
|
38
|
-
|
39
|
-
Esse.config.indices_directory.join(uname).to_s
|
40
|
-
end
|
41
|
-
|
42
|
-
def template_dirs
|
43
|
-
return [] unless index_directory
|
44
|
-
|
45
|
-
TEMPLATE_DIRS.map { |term| format(term, dirname: index_directory) }
|
46
|
-
end
|
47
|
-
|
48
|
-
protected
|
49
|
-
|
50
|
-
def index_prefixed_name(value)
|
51
|
-
return if value == '' || value.nil?
|
52
|
-
return value.to_s unless cluster.index_prefix
|
53
|
-
|
54
|
-
[cluster.index_prefix, value].join('_')
|
55
|
-
end
|
56
|
-
|
57
|
-
def normalized_name
|
58
|
-
Hstring.new(name).demodulize.underscore.sub(/_(index)$/, '')
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
extend ClassMethods
|
63
|
-
end
|
64
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Esse
|
4
|
-
class IndexType
|
5
|
-
# https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-put-mapping.html
|
6
|
-
module ClassMethods
|
7
|
-
# This method is only used to define mapping
|
8
|
-
def mappings(hash = {}, &block)
|
9
|
-
@mapping = Esse::IndexMapping.new(body: hash, paths: template_dirs, filenames: mapping_filenames)
|
10
|
-
return unless block
|
11
|
-
|
12
|
-
@mapping.define_singleton_method(:to_h, &block)
|
13
|
-
end
|
14
|
-
|
15
|
-
# This is the actually content that will be passed through the ES api
|
16
|
-
def mappings_hash
|
17
|
-
hash = mapping.body
|
18
|
-
{
|
19
|
-
type_name => (hash.key?('properties') ? hash : { 'properties' => hash }),
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def mapping
|
26
|
-
@mapping ||= Esse::IndexMapping.new(paths: template_dirs, filenames: mapping_filenames)
|
27
|
-
end
|
28
|
-
|
29
|
-
def template_dirs
|
30
|
-
return [] unless respond_to?(:index)
|
31
|
-
|
32
|
-
index.template_dirs
|
33
|
-
end
|
34
|
-
|
35
|
-
def mapping_filenames
|
36
|
-
Esse::IndexMapping::FILENAMES.map { |str| [type_name, str].join('_') }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
extend ClassMethods
|
41
|
-
end
|
42
|
-
end
|
data/lib/esse/index_type.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'object_document_mapper'
|
4
|
-
|
5
|
-
module Esse
|
6
|
-
# Type is actually deprecated. Elasticsearch today uses _doc instead of type
|
7
|
-
# And in upcoming release it will be totally removed.
|
8
|
-
# But I want to keep compatibility with old versions of es.
|
9
|
-
class IndexType
|
10
|
-
require_relative 'index_type/actions'
|
11
|
-
require_relative 'index_type/mappings'
|
12
|
-
require_relative 'index_type/backend'
|
13
|
-
extend ObjectDocumentMapper
|
14
|
-
end
|
15
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Esse
|
4
|
-
module ObjectDocumentMapper
|
5
|
-
# Convert ruby object to json. Arguments will be same of passed through the
|
6
|
-
# collection. It's allowed a block or a class with the `to_h` instance method.
|
7
|
-
# Example with block
|
8
|
-
# serializer do |model, **context|
|
9
|
-
# {
|
10
|
-
# id: model.id,
|
11
|
-
# admin: context[:is_admin],
|
12
|
-
# }
|
13
|
-
# end
|
14
|
-
# Example with serializer class
|
15
|
-
# serializer UserSerializer
|
16
|
-
def serializer(klass = nil, &block)
|
17
|
-
if block
|
18
|
-
@serializer_proc = block
|
19
|
-
elsif klass.is_a?(Class) && klass.instance_methods.include?(:to_h)
|
20
|
-
@serializer_proc = proc { |*args, **kwargs| klass.new(*args, **kwargs).to_h }
|
21
|
-
elsif klass.is_a?(Class) && klass.instance_methods.include?(:as_json) # backward compatibility
|
22
|
-
@serializer_proc = proc { |*args, **kwargs| klass.new(*args, **kwargs).as_json }
|
23
|
-
elsif klass.is_a?(Class) && klass.instance_methods.include?(:call)
|
24
|
-
@serializer_proc = proc { |*args, **kwargs| klass.new(*args, **kwargs).call }
|
25
|
-
else
|
26
|
-
msg = format('%<arg>p is not a valid serializer. The serializer should ' \
|
27
|
-
'respond with `to_h` instance method.', arg: klass,)
|
28
|
-
raise ArgumentError, msg
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def serialize(model, *args, **kwargs)
|
33
|
-
unless @serializer_proc
|
34
|
-
raise NotImplementedError, format('there is no serializer defined for the %<k>p index', k: to_s)
|
35
|
-
end
|
36
|
-
|
37
|
-
@serializer_proc.call(model, *args, **kwargs)
|
38
|
-
end
|
39
|
-
|
40
|
-
# Used to define the source of data. A block is required. And its
|
41
|
-
# content should yield an array of each object that should be serialized.
|
42
|
-
# The list of arguments will be passed throught the serializer method.
|
43
|
-
#
|
44
|
-
# Here is an example of how this should work:
|
45
|
-
# collection do |conditions, &block|
|
46
|
-
# User.where(conditions).find_in_batches(batch_size: 5000) do |batch|
|
47
|
-
# block.call(batch, conditions)
|
48
|
-
# end
|
49
|
-
# end
|
50
|
-
def collection(collection_class = nil, &block)
|
51
|
-
raise ArgumentError, 'a collection class or a block is required' if block.nil? && collection_class.nil?
|
52
|
-
|
53
|
-
if block.nil? && collection_class.is_a?(Class) && !collection_class.include?(Enumerable)
|
54
|
-
msg = '%<arg>p is not a valid collection class.' \
|
55
|
-
' Collections should implement the Enumerable interface'
|
56
|
-
raise ArgumentError, format(msg, arg: collection_class)
|
57
|
-
end
|
58
|
-
|
59
|
-
@collection_proc = collection_class || block
|
60
|
-
end
|
61
|
-
|
62
|
-
# Used to fetch all batch of data defined on the collection model.
|
63
|
-
# Arguments can be anything. They will just be passed through the block.
|
64
|
-
# Useful when the collection depends on scope or any other conditions
|
65
|
-
# Example
|
66
|
-
# each_batch(active: true) do |data, _opts|
|
67
|
-
# puts data.size
|
68
|
-
# end
|
69
|
-
def each_batch(*args, **kwargs, &block)
|
70
|
-
unless @collection_proc
|
71
|
-
raise NotImplementedError, format('there is no collection defined for the %<k>p index', k: to_s)
|
72
|
-
end
|
73
|
-
|
74
|
-
case @collection_proc
|
75
|
-
when Class
|
76
|
-
@collection_proc.new(*args, **kwargs).each(&block)
|
77
|
-
else
|
78
|
-
@collection_proc.call(*args, **kwargs, &block)
|
79
|
-
end
|
80
|
-
rescue LocalJumpError
|
81
|
-
raise(SyntaxError, 'block must be explicitly declared in the collection definition')
|
82
|
-
end
|
83
|
-
|
84
|
-
# Wrap collection data into serialized batches
|
85
|
-
#
|
86
|
-
# @param args [*Object] Any argument is allowed here. The collection will be called with same arguments.
|
87
|
-
# And the serializer will be initialized with those arguments too.
|
88
|
-
# @yield [Array, *Object] serialized collection and method arguments
|
89
|
-
def each_serialized_batch(**kwargs, &block)
|
90
|
-
each_batch(**kwargs) do |*batch, **collection_kwargs|
|
91
|
-
entries = batch.flatten.map { |entry| serialize(entry, **collection_kwargs) }.compact
|
92
|
-
block.call(entries, **kwargs)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# Wrap collection data into serialized documents
|
97
|
-
#
|
98
|
-
# Example:
|
99
|
-
# GeosIndex.documents(id: 1).first
|
100
|
-
#
|
101
|
-
# @return [Enumerator] All serialized entries
|
102
|
-
def documents(**kwargs)
|
103
|
-
Enumerator.new do |yielder|
|
104
|
-
each_serialized_batch(**kwargs) do |documents, **_collection_kargs|
|
105
|
-
documents.each { |document| yielder.yield(document) }
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|