elasticsearch_record 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +4 -0
  3. data/Gemfile.lock +10 -14
  4. data/README.md +180 -27
  5. data/docs/CHANGELOG.md +36 -18
  6. data/docs/LICENSE.txt +1 -1
  7. data/elasticsearch_record.gemspec +42 -0
  8. data/lib/active_record/connection_adapters/elasticsearch/column.rb +20 -6
  9. data/lib/active_record/connection_adapters/elasticsearch/database_statements.rb +142 -125
  10. data/lib/active_record/connection_adapters/elasticsearch/quoting.rb +2 -23
  11. data/lib/active_record/connection_adapters/elasticsearch/schema_creation.rb +30 -0
  12. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb +103 -0
  13. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb +42 -0
  14. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +158 -0
  15. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb +32 -0
  16. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +132 -0
  17. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb +110 -0
  18. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +136 -0
  19. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +174 -0
  20. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +37 -0
  21. data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +110 -0
  22. data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +398 -174
  23. data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +232 -0
  24. data/lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb +2 -0
  25. data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +32 -0
  26. data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +112 -19
  27. data/lib/arel/collectors/elasticsearch_query.rb +0 -1
  28. data/lib/arel/visitors/elasticsearch.rb +7 -579
  29. data/lib/arel/visitors/elasticsearch_base.rb +234 -0
  30. data/lib/arel/visitors/elasticsearch_query.rb +463 -0
  31. data/lib/arel/visitors/elasticsearch_schema.rb +124 -0
  32. data/lib/elasticsearch_record/core.rb +44 -10
  33. data/lib/elasticsearch_record/errors.rb +13 -0
  34. data/lib/elasticsearch_record/gem_version.rb +6 -2
  35. data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +27 -9
  36. data/lib/elasticsearch_record/model_schema.rb +5 -0
  37. data/lib/elasticsearch_record/persistence.rb +31 -26
  38. data/lib/elasticsearch_record/query.rb +56 -17
  39. data/lib/elasticsearch_record/querying.rb +17 -0
  40. data/lib/elasticsearch_record/relation/calculation_methods.rb +3 -0
  41. data/lib/elasticsearch_record/relation/core_methods.rb +57 -17
  42. data/lib/elasticsearch_record/relation/query_clause_tree.rb +38 -1
  43. data/lib/elasticsearch_record/relation/query_methods.rb +6 -0
  44. data/lib/elasticsearch_record/relation/result_methods.rb +15 -9
  45. data/lib/elasticsearch_record/result.rb +32 -5
  46. data/lib/elasticsearch_record/statement_cache.rb +2 -1
  47. data/lib/elasticsearch_record.rb +2 -2
  48. metadata +29 -11
  49. data/.ruby-version +0 -1
  50. data/lib/elasticsearch_record/schema_migration.rb +0 -30
@@ -3,202 +3,426 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module Elasticsearch
6
- module SchemaStatements # :nodoc:
6
+ # extend adapter with schema-related statements
7
+ #
8
+ # *ORIGINAL* methods untouched:
9
+ # - internal_string_options_for_primary_key
10
+ # - options_include_default?
11
+ # - fetch_type_metadata
12
+ # - column_exists?
13
+ #
14
+ # *SUPPORTED* but not used:
15
+ # - strip_table_name_prefix_and_suffix
16
+ #
17
+ # *UNSUPPORTED* methods that will be +ignored+:
18
+ # - native_database_types
19
+ # - table_options
20
+ # - table_comment
21
+ # - table_alias_for
22
+ # - columns_for_distinct
23
+ # - extract_new_default_value
24
+ # - insert_versions_sql
25
+ # - data_source_sql
26
+ # - quoted_scope
27
+ # - add_column_for_alter
28
+ # - rename_column_sql
29
+ # - remove_column_for_alter
30
+ # - remove_columns_for_alter
31
+ # - add_timestamps_for_alter
32
+ # - remove_timestamps_for_alter
33
+ # - foreign_key_name
34
+ # - foreign_key_for
35
+ # - foreign_key_for!
36
+ # - extract_foreign_key_action
37
+ # - check_constraint_name
38
+ # - check_constraint_for
39
+ # - check_constraint_for!
40
+ # - validate_index_length!
41
+ # - can_remove_index_by_name?
42
+ # - index_column_names
43
+ # - index_name_options
44
+ # - add_index_sort_order
45
+ # - options_for_index_columns
46
+ # - add_options_for_index_columns
47
+ # - index_name_for_remove
48
+ # - add_index_options
49
+ # - index_algorithm
50
+ # - quoted_columns_for_index
51
+ # - check_constraint_options
52
+ # - check_constraints
53
+ # - foreign_key_exists?
54
+ # - foreign_key_column_for
55
+ # - foreign_key_options
56
+ # - foreign_keys
57
+ # - index_name_exists?
58
+ # - indexes
59
+ # - index_name
60
+ # - index_exists?
61
+ #
62
+ # *UNSUPPORTED* methods that will +fail+:
63
+ # - views
64
+ # - view_exists?
65
+ # - add_index
66
+ # - remove_index
67
+ # - rename_index
68
+ # - add_reference
69
+ # - remove_reference
70
+ # - add_foreign_key
71
+ # - remove_foreign_key
72
+ # - add_check_constraint
73
+ # - remove_check_constraint
74
+ # - rename_table_indexes
75
+ # - rename_column_indexes
76
+ # - create_alter_table
77
+ # - insert_fixture
78
+ # - insert_fixtures_set
79
+ # - bulk_change_table
80
+ # - dump_schema_information
81
+ #
82
+ # OVERWRITTEN methods for Elasticsearch:
83
+ # ...
84
+ module SchemaStatements
85
+ extend ActiveSupport::Concern
7
86
 
8
- # temporary workaround
9
- # toDo: fixme
10
- def create_table(*args)
11
- $stdout.puts "\n>>> 'create_table' elasticsearch is not supported - the following message is insignificant!"
12
- end
87
+ included do
88
+ define_unsupported_method :views, :view_exists?, :add_index, :remove_index, :rename_index, :add_reference,
89
+ :remove_reference, :add_foreign_key, :remove_foreign_key, :add_check_constraint,
90
+ :remove_check_constraint, :rename_table_indexes, :rename_column_indexes,
91
+ :create_alter_table, :insert_fixture, :insert_fixtures_set, :bulk_change_table,
92
+ :dump_schema_information
13
93
 
14
- # temporary workaround
15
- # toDo: fixme
16
- def assume_migrated_upto_version(version)
17
- $stdout.puts "\n>>> 'assume_migrated_upto_version' elasticsearch is not supported - the following message is insignificant!"
18
- end
94
+ def assume_migrated_upto_version(version)
95
+ version = version.to_i
96
+ migrated = migration_context.get_all_versions
97
+ versions = migration_context.migrations.map(&:version)
19
98
 
99
+ unless migrated.include?(version)
100
+ # use a ActiveRecord syntax to create a new version
101
+ schema_migration.create(version: version)
102
+ end
20
103
 
104
+ inserting = (versions - migrated).select { |v| v < version }
105
+ if inserting.any?
106
+ if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
107
+ raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
108
+ end
21
109
 
110
+ # use a ActiveRecord syntax to create new versions
111
+ inserting.each {|iversion| schema_migration.create(version: iversion) }
112
+ end
22
113
 
114
+ true
115
+ end
23
116
 
24
- # Returns the relation names usable to back Active Record models.
25
- # For Elasticsearch this means all indices - which also includes system +dot+ '.' indices.
26
- # @see ActiveRecord::ConnectionAdapters::SchemaStatements#data_sources
27
- # @return [Array<String>]
28
- def data_sources
29
- api(:indices, :get_settings, { index: :_all }, 'SCHEMA').keys
30
- end
117
+ # Returns the relation names usable to back Active Record models.
118
+ # For Elasticsearch this means all indices - which also includes system +dot+ '.' indices.
119
+ # @see ActiveRecord::ConnectionAdapters::SchemaStatements#data_sources
120
+ # @return [Array<String>]
121
+ def data_sources
122
+ api(:indices, :get, { index: :_all, expand_wildcards: [:open, :closed] }, 'SCHEMA').keys
123
+ end
31
124
 
32
- # returns a hash of all mappings by provided index_name
33
- # @param [String] index_name
34
- # @return [Hash]
35
- def mappings(index_name)
36
- api(:indices, :get_mapping, { index: index_name }, 'SCHEMA').dig(index_name, 'mappings')
37
- end
125
+ # Returns an array of table names defined in the database.
126
+ # For Elasticsearch this means all normal indices (no system +dot+ '.' indices)
127
+ # @see ActiveRecord::ConnectionAdapters::SchemaStatements#tables
128
+ # @return [Array<String>]
129
+ def tables
130
+ data_sources.reject { |key| key[0] == '.' }
131
+ end
38
132
 
39
- # returns a hash of all settings by provided index_name
40
- # @param [String] index_name
41
- # @return [Hash]
42
- def settings(index_name)
43
- api(:indices, :get_settings, { index: index_name }, 'SCHEMA').dig(index_name, 'settings', 'index')
44
- end
133
+ # returns a hash of all mappings by provided table_name (index)
134
+ # @param [String] table_name
135
+ # @return [Hash]
136
+ def table_mappings(table_name)
137
+ api(:indices, :get_mapping, { index: table_name, expand_wildcards: [:open, :closed] }, 'SCHEMA').dig(table_name, 'mappings')
138
+ end
45
139
 
46
- # Returns the list of a table's column names, data types, and default values.
47
- # @see ActiveRecord::ConnectionAdapters::SchemaStatements#columns
48
- # @see ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#column_definitions
49
- # @param [String] table_name
50
- # @return [Array<Hash>]
51
- def column_definitions(table_name)
52
- structure = mappings(table_name)
53
- raise(ActiveRecord::StatementInvalid, "Could not find elasticsearch index '#{table_name}'") if structure.blank? || structure['properties'].blank?
54
-
55
- # since the received mappings do not have the "primary" +_id+-column we manually need to add this here
56
- # The BASE_STRUCTURE will also include some meta keys like '_score', '_type', ...
57
- ActiveRecord::ConnectionAdapters::ElasticsearchAdapter::BASE_STRUCTURE + structure['properties'].map { |key, prop|
58
- # resolve (nested) fields and properties
59
- fields, properties = resolve_fields_and_properties(key, prop, true)
60
-
61
- # fallback for possible empty type
62
- type = prop['type'].presence || (properties.present? ? 'object' : 'nested')
63
-
64
- # return a new hash
65
- prop.merge('name' => key, 'type' => type, 'fields' => fields, 'properties' => properties)
66
- }
67
- end
140
+ # returns a hash of all settings by provided table_name
141
+ # @param [String] table_name
142
+ # @param [Boolean] flat_settings (default: true)
143
+ # @return [Hash]
144
+ def table_settings(table_name, flat_settings = true)
145
+ api(:indices, :get_settings, { index: table_name, expand_wildcards: [:open, :closed], flat_settings: flat_settings }, 'SCHEMA').dig(table_name, 'settings')
146
+ end
68
147
 
69
- # creates a new column object from provided field Hash
70
- # @see ActiveRecord::ConnectionAdapters::SchemaStatements#columns
71
- # @see ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#new_column_from_field
72
- # @param [String] _table_name
73
- # @param [Hash] field
74
- # @return [ActiveRecord::ConnectionAdapters::Column]
75
- def new_column_from_field(_table_name, field)
76
- ActiveRecord::ConnectionAdapters::Elasticsearch::Column.new(
77
- field["name"],
78
- field["null_value"],
79
- fetch_type_metadata(field["type"]),
80
- field['null'].nil? ? true : field['null'],
81
- nil,
82
- comment: field['meta'] ? field['meta'].map { |k, v| "#{k}: #{v}" }.join(' | ') : nil,
83
- virtual: field['virtual'],
84
- fields: field['fields'],
85
- properties: field['properties']
86
- )
87
- end
148
+ # returns a hash of all aliases by provided table_name (index).
149
+ # @param [String] table_name
150
+ # @return [Hash]
151
+ def table_aliases(table_name)
152
+ api(:indices, :get_alias, { index: table_name, expand_wildcards: [:open, :closed] }, 'SCHEMA').dig(table_name, 'aliases')
153
+ end
88
154
 
89
- # lookups from building the @columns_hash.
90
- # since Elasticsearch has the "feature" to provide multicast values on any type, we need to fetch them ...
91
- # you know, ES can return an integer or an array of integers for any column ...
92
- # @param [ActiveRecord::ConnectionAdapters::Elasticsearch::Column] column
93
- # @return [ActiveRecord::ConnectionAdapters::Elasticsearch::Type::MulticastValue]
94
- def lookup_cast_type_from_column(column)
95
- type_map.lookup(:multicast_value, super)
96
- end
155
+ # returns information about number of primaries and replicas, document counts, disk size, ... by provided table_name (index).
156
+ # @param [String] table_name
157
+ # @return [Hash]
158
+ def table_state(table_name)
159
+ response = api(:cat, :indices, { index: table_name, expand_wildcards: [:open, :closed] }, 'SCHEMA')
97
160
 
98
- # Returns a array of tables primary keys.
99
- # PLEASE NOTE: Elasticsearch does not have a concept of primary key.
100
- # The only thing that uniquely identifies a document is the index together with the +_id+.
101
- # To not break the "ConnectionAdapters" concept we simulate this through the BASE_STRUCTURE.
102
- # We know, we can just return '_id' here ...
103
- # @see ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#primary_keys
104
- # @param [String] _table_name
105
- def primary_keys(_table_name)
106
- ActiveRecord::ConnectionAdapters::ElasticsearchAdapter::BASE_STRUCTURE
107
- .select { |f| f["primary"] }
108
- .map { |f| f["name"] }
109
- end
161
+ [:health, :status, :name, :uuid, :pri, :rep, :docs_count, :docs_deleted, :store_size, :pri_store_size].zip(
162
+ response.body.split(' ')
163
+ ).to_h
164
+ end
110
165
 
111
- # Checks to see if the data source +name+ exists on the database.
112
- #
113
- # data_source_exists?(:ebooks)
114
- # @see ActiveRecord::ConnectionAdapters::SchemaStatements#data_source_exists?
115
- # @param [String, Symbol] name
116
- # @return [Boolean]
117
- def data_source_exists?(name)
118
- # response returns boolean
119
- api(:indices, :exists?, { index: name }, 'SCHEMA')
120
- end
166
+ # returns a hash of the full definition of the provided table_name (index).
167
+ # (includes settings, mappings & aliases)
168
+ # @param [String] table_name
169
+ # @param [Array, Symbol] features
170
+ # @return [Hash]
171
+ def table_schema(table_name, features = [:aliases, :mappings, :settings])
172
+ if cluster_info[:version] >= '8.5.0'
173
+ response = api(:indices, :get, { index: table_name, expand_wildcards: [:open, :closed], features: features, flat_settings: true }, 'SCHEMA')
174
+ else
175
+ response = api(:indices, :get, { index: table_name, expand_wildcards: [:open, :closed], flat_settings: true }, 'SCHEMA')
176
+ end
121
177
 
122
- # Returns an array of table names defined in the database.
123
- # For Elasticsearch this means all normal indices (no system +dot+ '.' indices)
124
- # @see ActiveRecord::ConnectionAdapters::SchemaStatements#tables
125
- # @return [Array<String>]
126
- def tables
127
- data_sources.reject { |key| key[0] == '.' }
128
- end
178
+ {
179
+ settings: response.dig(table_name, 'settings'),
180
+ mappings: response.dig(table_name, 'mappings'),
181
+ aliases: response.dig(table_name, 'aliases')
182
+ }
183
+ end
129
184
 
130
- # Checks to see if the table +table_name+ exists on the database.
131
- #
132
- # table_exists?(:developers)
133
- #
134
- # @see ActiveRecord::ConnectionAdapters::SchemaStatements#table_exists?
135
- # @param [String, Symbol] table_name
136
- # @return [Boolean]
137
- def table_exists?(table_name)
138
- # just reference to the data sources
139
- data_source_exists?(table_name)
140
- end
185
+ # Returns the list of a table's column names, data types, and default values.
186
+ # @see ActiveRecord::ConnectionAdapters::SchemaStatements#columns
187
+ # @see ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#column_definitions
188
+ # @param [String] table_name
189
+ # @return [Array<Hash>]
190
+ def column_definitions(table_name)
191
+ mappings = table_mappings(table_name)
141
192
 
142
- # returns the maximum allowed size for queries.
143
- # The query will raise an ActiveRecord::StatementInvalid if the requested limit is above this value.
144
- # @return [Integer]
145
- def max_result_window
146
- 10000
147
- end
193
+ # prevent exceptions on missing mappings, to provide the possibility to create them
194
+ # otherwise loading the table (index) will always fail!
195
+ mappings = { 'properties' => {} } if mappings.blank? || mappings['properties'].blank?
196
+ # raise(ActiveRecord::StatementInvalid, "Could not find valid mappings for '#{table_name}'") if mappings.blank? || mappings['properties'].blank?
197
+
198
+ # since the received mappings do not have the "primary" +_id+-column we manually need to add this here
199
+ # The BASE_STRUCTURE will also include some meta keys like '_score', '_type', ...
200
+ ActiveRecord::ConnectionAdapters::ElasticsearchAdapter::BASE_STRUCTURE + mappings['properties'].map { |key, prop|
201
+ # resolve (nested) fields and properties
202
+ fields, properties = resolve_fields_and_properties(key, prop, true)
203
+
204
+ # fallback for possible empty type
205
+ type = prop['type'].presence || (properties.present? ? 'object' : 'nested')
206
+
207
+ # return a new hash
208
+ prop.merge('name' => key, 'type' => type, 'fields' => fields, 'properties' => properties)
209
+ }
210
+ end
211
+
212
+ # creates a new column object from provided field Hash
213
+ # @see ActiveRecord::ConnectionAdapters::SchemaStatements#columns
214
+ # @see ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#new_column_from_field
215
+ # @param [String] _table_name
216
+ # @param [Hash] field
217
+ # @return [ActiveRecord::ConnectionAdapters::Column]
218
+ def new_column_from_field(_table_name, field)
219
+ ActiveRecord::ConnectionAdapters::Elasticsearch::Column.new(
220
+ field["name"],
221
+ field["null_value"],
222
+ fetch_type_metadata(field["type"]),
223
+ meta: field['meta'],
224
+ virtual: field['virtual'],
225
+ fields: field['fields'],
226
+ properties: field['properties']
227
+ )
228
+ end
229
+
230
+ # lookups from building the @columns_hash.
231
+ # since Elasticsearch has the "feature" to provide multicast values on any type, we need to fetch them ...
232
+ # you know, ES can return an integer or an array of integers for any column ...
233
+ # @param [ActiveRecord::ConnectionAdapters::Elasticsearch::Column] column
234
+ # @return [ActiveRecord::ConnectionAdapters::Elasticsearch::Type::MulticastValue]
235
+ def lookup_cast_type_from_column(column)
236
+ type_map.lookup(:multicast_value, super)
237
+ end
238
+
239
+ # Returns a array of tables primary keys.
240
+ # PLEASE NOTE: Elasticsearch does not have a concept of primary key.
241
+ # The only thing that uniquely identifies a document is the index together with the +_id+.
242
+ # To not break the "ConnectionAdapters" concept we simulate this through the +meta+ attribute.
243
+ # @see ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#primary_keys
244
+ # @param [String] table_name
245
+ def primary_keys(table_name)
246
+ column_definitions(table_name)
247
+ # ActiveRecord::ConnectionAdapters::ElasticsearchAdapter::BASE_STRUCTURE
248
+ .select { |f| f['meta'] && f['meta']['primary_key'] == 'true' }
249
+ # only take the last found primary key (if no custom primary_key was provided this will return +_id+ )
250
+ .map { |f| f["name"] }[-1..-1]
251
+ end
252
+
253
+ # Checks to see if the data source +name+ exists on the database.
254
+ #
255
+ # data_source_exists?(:ebooks)
256
+ # @see ActiveRecord::ConnectionAdapters::SchemaStatements#data_source_exists?
257
+ # @param [String, Symbol] name
258
+ # @return [Boolean]
259
+ def data_source_exists?(name)
260
+ # response returns boolean
261
+ api(:indices, :exists?, { index: name, expand_wildcards: [:open, :closed] }, 'SCHEMA')
262
+ end
263
+
264
+ # Checks to see if the table +table_name+ exists on the database.
265
+ #
266
+ # table_exists?(:developers)
267
+ #
268
+ # @see ActiveRecord::ConnectionAdapters::SchemaStatements#table_exists?
269
+ # @param [String, Symbol] table_name
270
+ # @return [Boolean]
271
+ def table_exists?(table_name)
272
+ # just reference to the data sources
273
+ data_source_exists?(table_name)
274
+ end
275
+
276
+ # Checks to see if a alias +alias_name+ within a table +table_name+ exists on the database.
277
+ #
278
+ # alias_exists?(:developers, 'my-alias')
279
+ #
280
+ # @param [String] table_name
281
+ # @param [String, Symbol] alias_name
282
+ # @return [Boolean]
283
+ def alias_exists?(table_name, alias_name)
284
+ table_aliases(table_name).keys.include?(alias_name.to_s)
285
+ end
286
+
287
+ # Checks to see if a setting +setting_name+ within a table +table_name+ exists on the database.
288
+ # The provided +setting_name+ must be flat!
289
+ #
290
+ # setting_exists?(:developers, 'index.number_of_replicas')
291
+ #
292
+ # @param [String] table_name
293
+ # @param [String,Symbol] setting_name
294
+ # @return [Boolean]
295
+ def setting_exists?(table_name, setting_name)
296
+ table_settings(table_name).keys.include?(setting_name.to_s)
297
+ end
298
+
299
+ # Checks to see if a mapping +mapping_name+ within a table +table_name+ exists on the database.
300
+ #
301
+ # mapping_exists?(:developers, :status, :integer)
302
+ #
303
+ # @param [String, Symbol] table_name
304
+ # @param [String, Symbol] mapping_name
305
+ # @return [Boolean]
306
+ def mapping_exists?(table_name, mapping_name, type = nil)
307
+ column_exists?(table_name, mapping_name, type)
308
+ end
309
+
310
+ # overwrite original methods to provide a elasticsearch version
311
+ def create_schema_dumper(options)
312
+ ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaDumper.create(self, options)
313
+ end
314
+
315
+ # overwrite original methods to provide a elasticsearch version
316
+ def create_table_definition(name, **options)
317
+ ::ActiveRecord::ConnectionAdapters::Elasticsearch::CreateTableDefinition.new(self, name, **options)
318
+ end
319
+
320
+ # overwrite original methods to provide a elasticsearch version
321
+ def update_table_definition(name, base = self, **options)
322
+ # :nodoc:
323
+ ::ActiveRecord::ConnectionAdapters::Elasticsearch::UpdateTableDefinition.new(base, name, **options)
324
+ end
148
325
 
149
- private
150
-
151
- # returns a multidimensional array with fields & properties from the provided +prop+.
152
- # Nested fields & properties will be also detected.
153
- # .
154
- # resolve_fields_and_properties('user', {...})
155
- # # > [
156
- # # fields
157
- # [0] [
158
- # [0] {
159
- # "name" => "user.name.analyzed",
160
- # "type" => "text"
161
- # }
162
- # ],
163
- # # properties
164
- # [1] [
165
- # [0] {
166
- # "name" => "user.id",
167
- # "type" => "integer"
168
- # },
169
- # [1] {
170
- # "name" => "user.name",
171
- # "type" => "keyword"
172
- # }
173
- # ]
174
- # ]
175
- #
176
- # @param [String] key
177
- # @param [Hash] prop
178
- # @param [Boolean] root - provide true, if this is a top property entry (default: false)
179
- # @return [[Array, Array]]
180
- def resolve_fields_and_properties(key, prop, root = false)
181
- # mappings can have +fields+ - we also want them for 'query-conditions'
182
- fields = (prop['fields'] || {}).map { |field_key, field_def|
183
- { 'name' => "#{key}.#{field_key}", 'type' => field_def['type'] }
184
- }
185
-
186
- # initial empty array
187
- properties = []
188
-
189
- if prop['properties'].present?
190
- prop['properties'].each do |nested_key, nested_prop|
191
- nested_fields, nested_properties = resolve_fields_and_properties("#{key}.#{nested_key}", nested_prop)
192
- fields |= nested_fields
193
- properties |= nested_properties
326
+ # overwrite original methods to provide a elasticsearch version
327
+ def schema_creation
328
+ ::ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaCreation.new(self)
329
+ end
330
+
331
+ # returns the maximum allowed size for queries for the provided +table_name+.
332
+ # The query will raise an ActiveRecord::StatementInvalid if the requested limit is above this value.
333
+ # @return [Integer]
334
+ def max_result_window(table_name)
335
+ table_settings(table_name).dig('index', 'max_result_window').presence || 10000
336
+ end
337
+
338
+ # Returns basic information about the cluster.
339
+ # @return [Hash{Symbol->Unknown}]
340
+ def cluster_info
341
+ @cluster_info ||= begin
342
+ response = api(:core, :info, {}, 'CLUSTER')
343
+
344
+ {
345
+ name: response.dig('name'),
346
+ cluster_name: response.dig('cluster_name'),
347
+ cluster_uuid: response.dig('cluster_uuid'),
348
+ version: Gem::Version.new(response.dig('version', 'number')),
349
+ lucene_version: response.dig('version', 'lucene_version')
350
+ }
351
+ end
352
+ end
353
+
354
+ # transforms provided schema-type to a sql-type
355
+ # @param [String, Symbol] type
356
+ # @param [String]
357
+ def type_to_sql(type, **)
358
+ return '' if type.blank?
359
+
360
+ if (native = native_database_types[type.to_sym])
361
+ (native.is_a?(Hash) ? native[:name] : native).dup
362
+ else
363
+ type.to_s
194
364
  end
195
- elsif !root # don't add the root property as sub-property
196
- properties << { 'name' => key, 'type' => prop['type'] }
197
365
  end
198
366
 
199
- [fields, properties]
367
+ private
368
+
369
+ # returns a multidimensional array with fields & properties from the provided +prop+.
370
+ # Nested fields & properties will be also detected.
371
+ # .
372
+ # resolve_fields_and_properties('user', {...})
373
+ # # > [
374
+ # # fields
375
+ # [0] [
376
+ # [0] {
377
+ # "name" => "user.name.analyzed",
378
+ # "type" => "text"
379
+ # }
380
+ # ],
381
+ # # properties
382
+ # [1] [
383
+ # [0] {
384
+ # "name" => "user.id",
385
+ # "type" => "integer"
386
+ # },
387
+ # [1] {
388
+ # "name" => "user.name",
389
+ # "type" => "keyword"
390
+ # }
391
+ # ]
392
+ # ]
393
+ #
394
+ # @param [String] key
395
+ # @param [Hash] prop
396
+ # @param [Boolean] root - provide true, if this is a top property entry (default: false)
397
+ # @return [[Array, Array]]
398
+ def resolve_fields_and_properties(key, prop, root = false)
399
+ # mappings can have +fields+ - we also want them for 'query-conditions'
400
+ fields = (prop['fields'] || {}).map { |field_key, field_def|
401
+ { 'name' => "#{key}.#{field_key}", 'type' => field_def['type'] }
402
+ }
403
+
404
+ # initial empty array
405
+ properties = []
406
+
407
+ if prop['properties'].present?
408
+ prop['properties'].each do |nested_key, nested_prop|
409
+ nested_fields, nested_properties = resolve_fields_and_properties("#{key}.#{nested_key}", nested_prop)
410
+ fields |= nested_fields
411
+ properties |= nested_properties
412
+ end
413
+ elsif !root # don't add the root property as sub-property
414
+ properties << { 'name' => key, 'type' => prop['type'] }
415
+ end
416
+
417
+ [fields, properties]
418
+ end
419
+
420
+ # overwrite original methods to provide a elasticsearch version
421
+ def extract_table_options!(options)
422
+ options.extract!(:settings, :mappings, :aliases, :force, :strict)
423
+ end
200
424
  end
201
425
  end
202
426
  end
203
427
  end
204
- end
428
+ end