esse 0.2.0 → 0.2.3
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/event_listener.rb +13 -0
- data/lib/esse/cli/generate.rb +53 -14
- data/lib/esse/cli/index/base_operation.rb +5 -13
- data/lib/esse/cli/index/close.rb +1 -1
- data/lib/esse/cli/index/create.rb +1 -1
- data/lib/esse/cli/index/delete.rb +1 -1
- data/lib/esse/cli/index/import.rb +6 -2
- data/lib/esse/cli/index/open.rb +1 -1
- data/lib/esse/cli/index/reset.rb +1 -1
- data/lib/esse/cli/index/update_aliases.rb +2 -2
- data/lib/esse/cli/index/update_mapping.rb +9 -5
- data/lib/esse/cli/index/update_settings.rb +1 -1
- data/lib/esse/cli/index.rb +11 -4
- data/lib/esse/cli/templates/collection.rb.erb +29 -0
- data/lib/esse/cli/templates/config.rb.erb +13 -3
- data/lib/esse/cli/templates/document.rb.erb +34 -0
- data/lib/esse/cli/templates/index.rb.erb +63 -114
- data/lib/esse/cli/templates/mappings.json +27 -0
- data/lib/esse/cli/templates/settings.json +62 -0
- data/lib/esse/cli.rb +5 -0
- data/lib/esse/cluster.rb +93 -12
- 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 +28 -7
- data/lib/esse/deprecations/cluster.rb +27 -0
- data/lib/esse/deprecations/deprecate.rb +29 -0
- data/lib/esse/deprecations/index.rb +37 -0
- data/lib/esse/deprecations/index_backend_delegator.rb +217 -0
- data/lib/esse/deprecations/repository.rb +34 -0
- data/lib/esse/deprecations/repository_backend_delegator.rb +110 -0
- data/lib/esse/deprecations/serializer.rb +14 -0
- data/lib/esse/deprecations.rb +7 -0
- data/lib/esse/document.rb +91 -0
- data/lib/esse/dynamic_template.rb +43 -0
- data/lib/esse/errors.rb +60 -2
- data/lib/esse/events/event.rb +4 -19
- data/lib/esse/events.rb +13 -2
- data/lib/esse/hash_document.rb +38 -0
- data/lib/esse/import/bulk.rb +106 -0
- data/lib/esse/import/request_body.rb +60 -0
- data/lib/esse/index/aliases.rb +50 -0
- data/lib/esse/index/attributes.rb +107 -0
- data/lib/esse/index/base.rb +17 -53
- data/lib/esse/index/documents.rb +236 -0
- data/lib/esse/index/indices.rb +171 -0
- data/lib/esse/index/inheritance.rb +30 -0
- data/lib/esse/index/mappings.rb +6 -19
- data/lib/esse/index/object_document_mapper.rb +36 -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 +51 -11
- data/lib/esse/index.rb +14 -9
- 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/repository/documents.rb +13 -0
- data/lib/esse/repository/object_document_mapper.rb +157 -0
- data/lib/esse/repository.rb +17 -0
- data/lib/esse/search/query.rb +105 -0
- data/lib/esse/search/response.rb +46 -0
- data/lib/esse/template_loader.rb +1 -1
- data/lib/esse/transport/aliases.rb +36 -0
- data/lib/esse/transport/documents.rb +199 -0
- data/lib/esse/transport/health.rb +30 -0
- data/lib/esse/transport/indices.rb +192 -0
- data/lib/esse/transport/search.rb +48 -0
- data/lib/esse/transport.rb +44 -0
- data/lib/esse/version.rb +1 -1
- data/lib/esse.rb +20 -5
- metadata +55 -50
- data/lib/esse/backend/index/aliases.rb +0 -73
- data/lib/esse/backend/index/close.rb +0 -54
- data/lib/esse/backend/index/create.rb +0 -67
- data/lib/esse/backend/index/delete.rb +0 -39
- data/lib/esse/backend/index/documents.rb +0 -23
- data/lib/esse/backend/index/existance.rb +0 -22
- data/lib/esse/backend/index/open.rb +0 -54
- data/lib/esse/backend/index/refresh.rb +0 -43
- data/lib/esse/backend/index/reset.rb +0 -33
- data/lib/esse/backend/index/update.rb +0 -143
- data/lib/esse/backend/index.rb +0 -54
- 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_collection.rb.erb +0 -41
- 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/backend.rb +0 -14
- data/lib/esse/index/naming.rb +0 -64
- data/lib/esse/index_type/backend.rb +0 -14
- 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
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
# Delegates all the methods to the index ODM by prepending the type name.
|
5
|
+
#
|
6
|
+
# @see ObjectDocumentMapper
|
7
|
+
class Repository
|
8
|
+
module ClassMethods
|
9
|
+
# Convert ruby object to json. Arguments will be same of passed through the
|
10
|
+
# collection. It's allowed a block or a class with the `to_h` instance method.
|
11
|
+
# Example with block
|
12
|
+
# document do |model, **context|
|
13
|
+
# {
|
14
|
+
# id: model.id,
|
15
|
+
# admin: context[:is_admin],
|
16
|
+
# }
|
17
|
+
# end
|
18
|
+
# Example with document class
|
19
|
+
# document UserDocument
|
20
|
+
def document(klass = nil, &block)
|
21
|
+
if @document_proc
|
22
|
+
raise ArgumentError, format('Document for %p already defined', repo_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
if block
|
26
|
+
@document_proc = ->(model, **kwargs) { coerce_to_document(block.call(model, **kwargs)) }
|
27
|
+
elsif klass.is_a?(Class) && klass <= Esse::Document
|
28
|
+
@document_proc = ->(model, **kwargs) { klass.new(model, **kwargs) }
|
29
|
+
elsif klass.is_a?(Class) && klass.instance_methods.include?(:to_h)
|
30
|
+
@document_proc = ->(model, **kwargs) { coerce_to_document(klass.new(model, **kwargs).to_h) }
|
31
|
+
elsif klass.is_a?(Class) && klass.instance_methods.include?(:as_json) # backward compatibility
|
32
|
+
@document_proc = ->(model, **kwargs) { coerce_to_document(klass.new(model, **kwargs).as_json) }
|
33
|
+
elsif klass.is_a?(Class) && klass.instance_methods.include?(:call)
|
34
|
+
@document_proc = ->(model, **kwargs) { coerce_to_document(klass.new(model, **kwargs).call) }
|
35
|
+
else
|
36
|
+
msg = format("%<arg>p is not a valid document. The document should inherit from Esse::Document or respond to `to_h'", arg: klass)
|
37
|
+
raise ArgumentError, msg
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def coerce_to_document(value)
|
42
|
+
case value
|
43
|
+
when Esse::Document
|
44
|
+
value
|
45
|
+
when Hash
|
46
|
+
Esse::HashDocument.new(value)
|
47
|
+
when NilClass, FalseClass
|
48
|
+
Esse::NullDocument.new
|
49
|
+
else
|
50
|
+
raise ArgumentError, format('%<arg>p is not a valid document. The document should be a hash or an instance of Esse::Document', arg: value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Convert ruby object to json by using the document of the given document type.
|
55
|
+
# @param [Object] model The ruby object
|
56
|
+
# @param [Hash] kwargs The context
|
57
|
+
# @return [Esse::Document] The serialized document
|
58
|
+
def serialize(model, **kwargs)
|
59
|
+
if @document_proc.nil?
|
60
|
+
raise NotImplementedError, format('there is no %<t>p document defined for the %<k>p index', t: repo_name, k: index.to_s)
|
61
|
+
end
|
62
|
+
|
63
|
+
@document_proc.call(model, **kwargs)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Used to define the source of data. A block is required. And its
|
67
|
+
# content should yield an array of each object that should be serialized.
|
68
|
+
# The list of arguments will be passed throught the document method.
|
69
|
+
#
|
70
|
+
# Example:
|
71
|
+
# collection AdminStore
|
72
|
+
# collection do |**conditions, &block|
|
73
|
+
# User.where(conditions).find_in_batches(batch_size: 5000) do |batch|
|
74
|
+
# block.call(batch, conditions)
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# @param [String] name The identification of the collection.
|
79
|
+
# @param [Class] klass The class of the collection. (Optional when block is passed)
|
80
|
+
# @param [Proc] block The block that will be used to iterate over the collection. (Optional when using a class)
|
81
|
+
# @return [void]
|
82
|
+
def collection(collection_klass = nil, **_, &block)
|
83
|
+
if collection_klass.nil? && block.nil?
|
84
|
+
raise ArgumentError, 'a document type, followed by a collection class or block that stream the data ' \
|
85
|
+
'is required to define the collection'
|
86
|
+
end
|
87
|
+
|
88
|
+
if block.nil? && collection_klass.is_a?(Class) && !collection_klass.include?(Enumerable)
|
89
|
+
msg = '%<arg>p is not a valid collection class.' \
|
90
|
+
' Collections should implement the Enumerable interface.'
|
91
|
+
raise ArgumentError, format(msg, arg: collection_klass)
|
92
|
+
end
|
93
|
+
|
94
|
+
@collection_proc = collection_klass || block
|
95
|
+
end
|
96
|
+
|
97
|
+
# Used to fetch all batch of data defined on the collection model.
|
98
|
+
# Arguments can be anything. They will just be passed through the block.
|
99
|
+
# Useful when the collection depends on scope or any other conditions
|
100
|
+
#
|
101
|
+
# Example:
|
102
|
+
# each_batch(active: true) do |data, **_collection_opts|
|
103
|
+
# puts data.size
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# @todo Remove *args. It should only support keyword arguments
|
107
|
+
#
|
108
|
+
# @param [Hash] kwargs The context
|
109
|
+
# @param [Proc] block The block that will be used to iterate over the collection.
|
110
|
+
# @return [void]
|
111
|
+
def each_batch(*args, **kwargs, &block)
|
112
|
+
if @collection_proc.nil?
|
113
|
+
raise NotImplementedError, format('there is no %<t>p collection defined for the %<k>p index', t: repo_name, k: index.to_s)
|
114
|
+
end
|
115
|
+
|
116
|
+
case @collection_proc
|
117
|
+
when Class
|
118
|
+
@collection_proc.new(*args, **kwargs).each(&block)
|
119
|
+
else
|
120
|
+
@collection_proc.call(*args, **kwargs, &block)
|
121
|
+
end
|
122
|
+
rescue LocalJumpError
|
123
|
+
raise(SyntaxError, 'block must be explicitly declared in the collection definition')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Wrap collection data into serialized batches
|
127
|
+
#
|
128
|
+
# @param [Hash] kwargs The context
|
129
|
+
# @return [Enumerator] The enumerator
|
130
|
+
# @yield [Array, **context] serialized collection and the optional context from the collection
|
131
|
+
def each_serialized_batch(**kwargs, &block)
|
132
|
+
each_batch(**kwargs) do |*args|
|
133
|
+
batch, collection_context = args
|
134
|
+
collection_context ||= {}
|
135
|
+
entries = [*batch].map { |entry| serialize(entry, **collection_context) }.compact
|
136
|
+
block.call(entries, **kwargs)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Wrap collection data into serialized documents
|
141
|
+
#
|
142
|
+
# Example:
|
143
|
+
# GeosIndex.documents(id: 1).first
|
144
|
+
#
|
145
|
+
# @return [Enumerator] All serialized entries
|
146
|
+
def documents(**kwargs)
|
147
|
+
Enumerator.new do |yielder|
|
148
|
+
each_serialized_batch(**kwargs) do |docs, **_collection_kargs|
|
149
|
+
docs.each { |document| yielder.yield(document) }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
extend ClassMethods
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
# Type is actually deprecated. Elasticsearch today uses _doc instead of type
|
5
|
+
# And in upcoming release it will be totally removed.
|
6
|
+
# But I want to keep compatibility with old versions of es.
|
7
|
+
class Repository
|
8
|
+
class << self
|
9
|
+
# This methods will be defined using meta programming in the index respository definition
|
10
|
+
# @see Esse::Index::Type.repository
|
11
|
+
attr_reader :index
|
12
|
+
end
|
13
|
+
require_relative 'repository/actions'
|
14
|
+
require_relative 'repository/documents'
|
15
|
+
require_relative 'repository/object_document_mapper'
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
module Search
|
5
|
+
class Query
|
6
|
+
attr_reader :transport, :definition
|
7
|
+
|
8
|
+
# @param transport [Esse::Transport] The client proxy to use for the query
|
9
|
+
# @param indices [<Array<Esse::Index, String>] The class of the index to search or the index name
|
10
|
+
# @param definition [Hash] The options to pass to the search.
|
11
|
+
def initialize(transport, *indices, suffix: nil, **definition, &_block)
|
12
|
+
@transport = transport
|
13
|
+
@definition = definition
|
14
|
+
@definition[:index] = indices.map do |index|
|
15
|
+
if index.is_a?(Class) && index < Esse::Index
|
16
|
+
index.index_name(suffix: suffix)
|
17
|
+
elsif index.is_a?(String) || index.is_a?(Symbol)
|
18
|
+
[index, suffix].compact.join('_')
|
19
|
+
else
|
20
|
+
raise ArgumentError, format('Invalid index type: %<index>p. It should be a Esse::Index class or a String index name', index: index)
|
21
|
+
end
|
22
|
+
end.join(',')
|
23
|
+
end
|
24
|
+
|
25
|
+
def response
|
26
|
+
@response ||= execute_search_query!
|
27
|
+
end
|
28
|
+
|
29
|
+
def results
|
30
|
+
return paginated_results if respond_to?(:paginated_results, true)
|
31
|
+
|
32
|
+
response.hits
|
33
|
+
end
|
34
|
+
|
35
|
+
def scroll_hits(batch_size: 1_000, scroll: '1m')
|
36
|
+
response = execute_search_query!(size: batch_size, scroll: scroll)
|
37
|
+
scroll_id = nil
|
38
|
+
fetched = 0
|
39
|
+
total = response.total
|
40
|
+
|
41
|
+
loop do
|
42
|
+
fetched += response.hits.size
|
43
|
+
yield(response.hits) if response.hits.any?
|
44
|
+
break if fetched >= total
|
45
|
+
scroll_id = response.raw_response['scroll_id'] || response.raw_response['_scroll_id']
|
46
|
+
break unless scroll_id
|
47
|
+
response = execute_scroll_query(scroll: scroll, scroll_id: scroll_id)
|
48
|
+
end
|
49
|
+
ensure
|
50
|
+
begin
|
51
|
+
transport.clear_scroll(body: {scroll_id: scroll_id}) if scroll_id
|
52
|
+
rescue Esse::Transport::NotFoundError
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def execute_search_query!(**execution_options)
|
59
|
+
resp, err = nil
|
60
|
+
Esse::Events.instrument('elasticsearch.execute_search_query') do |payload|
|
61
|
+
payload[:query] = self
|
62
|
+
begin
|
63
|
+
resp = Response.new(self, transport.search(**definition, **execution_options))
|
64
|
+
rescue => e
|
65
|
+
err = e
|
66
|
+
end
|
67
|
+
payload[:error] = err if err
|
68
|
+
payload[:response] = resp
|
69
|
+
end
|
70
|
+
raise err if err
|
71
|
+
|
72
|
+
resp
|
73
|
+
end
|
74
|
+
|
75
|
+
def execute_scroll_query(scroll:, scroll_id:)
|
76
|
+
resp, err = nil
|
77
|
+
Esse::Events.instrument('elasticsearch.execute_search_query') do |payload|
|
78
|
+
payload[:query] = self
|
79
|
+
begin
|
80
|
+
resp = Response.new(self, transport.scroll(scroll: scroll, body: { scroll_id: scroll_id }))
|
81
|
+
rescue => e
|
82
|
+
err = e
|
83
|
+
end
|
84
|
+
payload[:error] = err if err
|
85
|
+
payload[:response] = resp
|
86
|
+
end
|
87
|
+
raise err if err
|
88
|
+
|
89
|
+
resp
|
90
|
+
end
|
91
|
+
|
92
|
+
def reset!
|
93
|
+
@response = nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def raw_limit_value
|
97
|
+
definition.dig(:body, :size) || definition.dig(:body, 'size') || definition.dig(:size) || definition.dig('size')
|
98
|
+
end
|
99
|
+
|
100
|
+
def raw_offset_value
|
101
|
+
definition.dig(:body, :from) || definition.dig(:body, 'from') || definition.dig(:from) || definition.dig('from')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
module Search
|
5
|
+
class Response
|
6
|
+
include Enumerable
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :hits, :each, :size, :empty?
|
10
|
+
attr_reader :query, :raw_response, :options
|
11
|
+
|
12
|
+
# @param [Esse::Search::Query] query The search query
|
13
|
+
# @param [Hash] raw_response The raw response from Elasticsearch
|
14
|
+
# @param [Hash] options The options passed to the search
|
15
|
+
def initialize(query, raw_response, **options)
|
16
|
+
@query = query
|
17
|
+
@raw_response = raw_response
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def shards
|
22
|
+
raw_response['_shards']
|
23
|
+
end
|
24
|
+
|
25
|
+
def aggregations
|
26
|
+
raw_response['aggregations']
|
27
|
+
end
|
28
|
+
|
29
|
+
def suggestions
|
30
|
+
raw_response['suggest']
|
31
|
+
end
|
32
|
+
|
33
|
+
def hits
|
34
|
+
raw_response.dig('hits', 'hits') || []
|
35
|
+
end
|
36
|
+
|
37
|
+
def total
|
38
|
+
if raw_response.dig('hits', 'total').respond_to?(:keys)
|
39
|
+
raw_response.dig('hits', 'total', 'value')
|
40
|
+
else
|
41
|
+
raw_response.dig('hits', 'total')
|
42
|
+
end.to_i
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/esse/template_loader.rb
CHANGED
@@ -24,7 +24,7 @@ module Esse
|
|
24
24
|
path = nil
|
25
25
|
@directories.each do |dir|
|
26
26
|
patterns.find do |pattern|
|
27
|
-
path = Dir[dir.join("#{pattern}.{#{@extensions.join(
|
27
|
+
path = Dir[dir.join("#{pattern}.{#{@extensions.join(',')}}")].first
|
28
28
|
break if path
|
29
29
|
end
|
30
30
|
break if path
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
class Transport
|
5
|
+
module InstanceMethods
|
6
|
+
# Return a list of index aliases.
|
7
|
+
#
|
8
|
+
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
9
|
+
# @option [String] :index A comma-separated list of index names to filter aliases
|
10
|
+
# @option [String] :name A comma-separated list of alias names to return
|
11
|
+
# @raise [Esse::Transport::ServerError] in case of failure
|
12
|
+
#
|
13
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/7.5/indices-get-alias.html
|
14
|
+
def aliases(**options)
|
15
|
+
coerce_exception { client.indices.get_alias(**options) }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Updates index aliases.
|
19
|
+
#
|
20
|
+
# @param options [Hash] Hash of paramenters that will be passed along to elasticsearch request
|
21
|
+
# @option [Hash] :body The definition of `actions` to perform
|
22
|
+
#
|
23
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
|
24
|
+
def update_aliases(body:, **options)
|
25
|
+
throw_error_when_readonly!
|
26
|
+
|
27
|
+
Esse::Events.instrument('elasticsearch.update_aliases') do |payload|
|
28
|
+
payload[:request] = options
|
29
|
+
payload[:response] = coerce_exception { client.indices.update_aliases(**options, body: body) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
include InstanceMethods
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
class Transport
|
5
|
+
module InstanceMethods
|
6
|
+
# Returns a document.
|
7
|
+
#
|
8
|
+
# @option [String] :id The document ID
|
9
|
+
# @option [String] :index The name of the index
|
10
|
+
# @option [Boolean] :force_synthetic_source Should this request force synthetic _source? Use this to test if the mapping supports synthetic _source and to get a sense of the worst case performance. Fetches with this enabled will be slower the enabling synthetic source natively in the index.
|
11
|
+
# @option [List] :stored_fields A comma-separated list of stored fields to return in the response
|
12
|
+
# @option [String] :preference Specify the node or shard the operation should be performed on (default: random)
|
13
|
+
# @option [Boolean] :realtime Specify whether to perform the operation in realtime or search mode
|
14
|
+
# @option [Boolean] :refresh Refresh the shard containing the document before performing the operation
|
15
|
+
# @option [String] :routing Specific routing value
|
16
|
+
# @option [List] :_source True or false to return the _source field or not, or a list of fields to return
|
17
|
+
# @option [List] :_source_excludes A list of fields to exclude from the returned _source field
|
18
|
+
# @option [List] :_source_includes A list of fields to extract and return from the _source field
|
19
|
+
# @option [Number] :version Explicit version number for concurrency control
|
20
|
+
# @option [String] :version_type Specific version type (options: internal, external, external_gte)
|
21
|
+
# @option [Hash] :headers Custom HTTP headers
|
22
|
+
#
|
23
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html
|
24
|
+
#
|
25
|
+
def get(id:, index:, **options)
|
26
|
+
Esse::Events.instrument('elasticsearch.get') do |payload|
|
27
|
+
payload[:request] = opts = options.merge(id: id, index: index)
|
28
|
+
payload[:response] = coerce_exception { client.get(**opts) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns information about whether a document exists in an index.
|
33
|
+
#
|
34
|
+
# @option [String] :id The document ID
|
35
|
+
# @option [String] :index The name of the index
|
36
|
+
# @option [List] :stored_fields A comma-separated list of stored fields to return in the response
|
37
|
+
# @option [String] :preference Specify the node or shard the operation should be performed on (default: random)
|
38
|
+
# @option [Boolean] :realtime Specify whether to perform the operation in realtime or search mode
|
39
|
+
# @option [Boolean] :refresh Refresh the shard containing the document before performing the operation
|
40
|
+
# @option [String] :routing Specific routing value
|
41
|
+
# @option [List] :_source True or false to return the _source field or not, or a list of fields to return
|
42
|
+
# @option [List] :_source_excludes A list of fields to exclude from the returned _source field
|
43
|
+
# @option [List] :_source_includes A list of fields to extract and return from the _source field
|
44
|
+
# @option [Number] :version Explicit version number for concurrency control
|
45
|
+
# @option [String] :version_type Specific version type (options: internal, external, external_gte)
|
46
|
+
# @option [Hash] :headers Custom HTTP headers
|
47
|
+
#
|
48
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html
|
49
|
+
#
|
50
|
+
def exist?(id:, index:, **options)
|
51
|
+
Esse::Events.instrument('elasticsearch.exist') do |payload|
|
52
|
+
payload[:request] = opts = options.merge(id: id, index: index)
|
53
|
+
payload[:response] = coerce_exception { client.exists(**opts) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns number of documents matching a query.
|
58
|
+
#
|
59
|
+
# @option [List] :index A comma-separated list of indices to restrict the results
|
60
|
+
# @option [Boolean] :ignore_unavailable Whether specified concrete indices should be ignored when unavailable (missing or closed)
|
61
|
+
# @option [Boolean] :ignore_throttled Whether specified concrete, expanded or aliased indices should be ignored when throttled
|
62
|
+
# @option [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)
|
63
|
+
# @option [String] :expand_wildcards Whether to expand wildcard expression to concrete indices that are open, closed or both. (options: open, closed, hidden, none, all)
|
64
|
+
# @option [Number] :min_score Include only documents with a specific `_score` value in the result
|
65
|
+
# @option [String] :preference Specify the node or shard the operation should be performed on (default: random)
|
66
|
+
# @option [List] :routing A comma-separated list of specific routing values
|
67
|
+
# @option [String] :q Query in the Lucene query string syntax
|
68
|
+
# @option [String] :analyzer The analyzer to use for the query string
|
69
|
+
# @option [Boolean] :analyze_wildcard Specify whether wildcard and prefix queries should be analyzed (default: false)
|
70
|
+
# @option [String] :default_operator The default operator for query string query (AND or OR) (options: AND, OR)
|
71
|
+
# @option [String] :df The field to use as default where no field prefix is given in the query string
|
72
|
+
# @option [Boolean] :lenient Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
|
73
|
+
# @option [Number] :terminate_after The maximum count for each shard, upon reaching which the query execution will terminate early
|
74
|
+
# @option [Hash] :headers Custom HTTP headers
|
75
|
+
# @option [Hash] :body A query to restrict the results specified with the Query DSL (optional)
|
76
|
+
#
|
77
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html
|
78
|
+
def count(index:, **options)
|
79
|
+
Esse::Events.instrument('elasticsearch.count') do |payload|
|
80
|
+
payload[:request] = opts = options.merge(index: index)
|
81
|
+
payload[:response] = coerce_exception { client.count(**opts) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Removes a document from the index.
|
86
|
+
#
|
87
|
+
# @option arguments [String] :id The document ID
|
88
|
+
# @option arguments [String] :index The name of the index
|
89
|
+
# @option arguments [String] :wait_for_active_shards Sets the number of shard copies that must be active before proceeding with the delete 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)
|
90
|
+
# @option arguments [String] :refresh If `true` then refresh the affected shards to make this operation visible to search, if `wait_for` then wait for a refresh to make this operation visible to search, if `false` (the default) then do nothing with refreshes. (options: true, false, wait_for)
|
91
|
+
# @option arguments [String] :routing Specific routing value
|
92
|
+
# @option arguments [Time] :timeout Explicit operation timeout
|
93
|
+
# @option arguments [Number] :if_seq_no only perform the delete operation if the last operation that has changed the document has the specified sequence number
|
94
|
+
# @option arguments [Number] :if_primary_term only perform the delete operation if the last operation that has changed the document has the specified primary term
|
95
|
+
# @option arguments [Number] :version Explicit version number for concurrency control
|
96
|
+
# @option arguments [String] :version_type Specific version type (options: internal, external, external_gte)
|
97
|
+
# @option arguments [Hash] :headers Custom HTTP headers
|
98
|
+
#
|
99
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html
|
100
|
+
def delete(id:, index:, **options)
|
101
|
+
throw_error_when_readonly!
|
102
|
+
|
103
|
+
Esse::Events.instrument('elasticsearch.delete') do |payload|
|
104
|
+
payload[:request] = opts = options.merge(id: id, index: index)
|
105
|
+
payload[:response] = coerce_exception { client.delete(**opts) }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Updates a document with a script or partial document.
|
110
|
+
#
|
111
|
+
# @option [String] :id Document ID
|
112
|
+
# @option [String] :index The name of the index
|
113
|
+
# @option [String] :wait_for_active_shards Sets the number of shard copies that must be active before proceeding with the update 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)
|
114
|
+
# @option [List] :_source True or false to return the _source field or not, or a list of fields to return
|
115
|
+
# @option [List] :_source_excludes A list of fields to exclude from the returned _source field
|
116
|
+
# @option [List] :_source_includes A list of fields to extract and return from the _source field
|
117
|
+
# @option [String] :lang The script language (default: painless)
|
118
|
+
# @option [String] :refresh If `true` then refresh the affected shards to make this operation visible to search, if `wait_for` then wait for a refresh to make this operation visible to search, if `false` (the default) then do nothing with refreshes. (options: true, false, wait_for)
|
119
|
+
# @option [Number] :retry_on_conflict Specify how many times should the operation be retried when a conflict occurs (default: 0)
|
120
|
+
# @option [String] :routing Specific routing value
|
121
|
+
# @option [Time] :timeout Explicit operation timeout
|
122
|
+
# @option [Number] :if_seq_no only perform the update operation if the last operation that has changed the document has the specified sequence number
|
123
|
+
# @option [Number] :if_primary_term only perform the update operation if the last operation that has changed the document has the specified primary term
|
124
|
+
# @option [Boolean] :require_alias When true, requires destination is an alias. Default is false
|
125
|
+
# @option [Hash] :headers Custom HTTP headers
|
126
|
+
# @option [Hash] :body The request definition requires either `script` or partial `doc` (*Required*)
|
127
|
+
#
|
128
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
|
129
|
+
#
|
130
|
+
def update(id:, index:, body:, **options)
|
131
|
+
throw_error_when_readonly!
|
132
|
+
|
133
|
+
Esse::Events.instrument('elasticsearch.update') do |payload|
|
134
|
+
payload[:request] = opts = options.merge(id: id, index: index, body: body)
|
135
|
+
payload[:response] = coerce_exception { client.update(**opts) }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Creates or updates a document in an index.
|
140
|
+
#
|
141
|
+
# @option [String] :id Document ID
|
142
|
+
# @option [String] :index The name of the index
|
143
|
+
# @option [String] :wait_for_active_shards Sets the number of shard copies that must be active before proceeding with the index 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)
|
144
|
+
# @option [String] :op_type Explicit operation type. Defaults to `index` for requests with an explicit document ID, and to `create`for requests without an explicit document ID (options: index, create)
|
145
|
+
# @option [String] :refresh If `true` then refresh the affected shards to make this operation visible to search, if `wait_for` then wait for a refresh to make this operation visible to search, if `false` (the default) then do nothing with refreshes. (options: true, false, wait_for)
|
146
|
+
# @option [String] :routing Specific routing value
|
147
|
+
# @option [Time] :timeout Explicit operation timeout
|
148
|
+
# @option [Number] :version Explicit version number for concurrency control
|
149
|
+
# @option [String] :version_type Specific version type (options: internal, external, external_gte)
|
150
|
+
# @option [Number] :if_seq_no only perform the index operation if the last operation that has changed the document has the specified sequence number
|
151
|
+
# @option [Number] :if_primary_term only perform the index operation if the last operation that has changed the document has the specified primary term
|
152
|
+
# @option [String] :pipeline The pipeline id to preprocess incoming documents with
|
153
|
+
# @option [Boolean] :require_alias When true, requires destination to be an alias. Default is false
|
154
|
+
# @option [Hash] :headers Custom HTTP headers
|
155
|
+
# @option [Hash] :body The document (*Required*)
|
156
|
+
#
|
157
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
|
158
|
+
def index(id:, index:, body:, **options)
|
159
|
+
throw_error_when_readonly!
|
160
|
+
|
161
|
+
Esse::Events.instrument('elasticsearch.index') do |payload|
|
162
|
+
payload[:request] = opts = options.merge(id: id, index: index, body: body)
|
163
|
+
payload[:response] = coerce_exception { client.index(**opts) }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Allows to perform multiple index/update/delete operations in a single request.
|
168
|
+
#
|
169
|
+
# @option arguments [String] :index Default index for items which don't provide one
|
170
|
+
# @option arguments [String] :wait_for_active_shards Sets the number of shard copies that must be active before proceeding with the bulk 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)
|
171
|
+
# @option arguments [String] :refresh If `true` then refresh the affected shards to make this operation visible to search, if `wait_for` then wait for a refresh to make this operation visible to search, if `false` (the default) then do nothing with refreshes. (options: true, false, wait_for)
|
172
|
+
# @option arguments [String] :routing Specific routing value
|
173
|
+
# @option arguments [Time] :timeout Explicit operation timeout
|
174
|
+
# @option arguments [String] :type Default document type for items which don't provide one
|
175
|
+
# @option arguments [List] :_source True or false to return the _source field or not, or default list of fields to return, can be overridden on each sub-request
|
176
|
+
# @option arguments [List] :_source_excludes Default list of fields to exclude from the returned _source field, can be overridden on each sub-request
|
177
|
+
# @option arguments [List] :_source_includes Default list of fields to extract and return from the _source field, can be overridden on each sub-request
|
178
|
+
# @option arguments [String] :pipeline The pipeline id to preprocess incoming documents with
|
179
|
+
# @option arguments [Boolean] :require_alias Sets require_alias for all incoming documents. Defaults to unset (false)
|
180
|
+
# @option arguments [Hash] :headers Custom HTTP headers
|
181
|
+
# @option arguments [String|Array] :body The operation definition and data (action-data pairs), separated by newlines. Array of Strings, Header/Data pairs,
|
182
|
+
# or the conveniency "combined" format can be passed, refer to Elasticsearch::API::Utils.__bulkify documentation.
|
183
|
+
#
|
184
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
|
185
|
+
def bulk(body:, **options)
|
186
|
+
throw_error_when_readonly!
|
187
|
+
|
188
|
+
Esse::Events.instrument('elasticsearch.bulk') do |payload|
|
189
|
+
payload[:request] = opts = options.merge(body: body)
|
190
|
+
payload[:response] = response = coerce_exception { client.bulk(**opts) }
|
191
|
+
yield(payload) if block_given? # Allow caller to add data to the payload of event
|
192
|
+
response
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
include InstanceMethods
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esse
|
4
|
+
class Transport
|
5
|
+
module InstanceMethods
|
6
|
+
# Returns basic information about the health of the cluster.
|
7
|
+
#
|
8
|
+
# @option [List] :index Limit the information returned to a specific index
|
9
|
+
# @option [String] :expand_wildcards Whether to expand wildcard expression to concrete indices that are open, closed or both. (options: open, closed, hidden, none, all)
|
10
|
+
# @option [String] :level Specify the level of detail for returned information (options: cluster, indices, shards)
|
11
|
+
# @option [Boolean] :local Return local information, do not retrieve the state from master node (default: false)
|
12
|
+
# @option [Time] :master_timeout Explicit operation timeout for connection to master node
|
13
|
+
# @option [Time] :timeout Explicit operation timeout
|
14
|
+
# @option [String] :wait_for_active_shards Wait until the specified number of shards is active
|
15
|
+
# @option [String] :wait_for_nodes Wait until the specified number of nodes is available
|
16
|
+
# @option [String] :wait_for_events Wait until all currently queued events with the given priority are processed (options: immediate, urgent, high, normal, low, languid)
|
17
|
+
# @option [Boolean] :wait_for_no_relocating_shards Whether to wait until there are no relocating shards in the cluster
|
18
|
+
# @option [Boolean] :wait_for_no_initializing_shards Whether to wait until there are no initializing shards in the cluster
|
19
|
+
# @option [String] :wait_for_status Wait until cluster is in a specific state (options: green, yellow, red)
|
20
|
+
# @option [Hash] :headers Custom HTTP headers
|
21
|
+
#
|
22
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html
|
23
|
+
def health(**options)
|
24
|
+
coerce_exception { client.cluster.health(**options) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
include InstanceMethods
|
29
|
+
end
|
30
|
+
end
|