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.
- checksums.yaml +4 -4
- data/.yardopts +4 -0
- data/Gemfile.lock +10 -14
- data/README.md +180 -27
- data/docs/CHANGELOG.md +36 -18
- data/docs/LICENSE.txt +1 -1
- data/elasticsearch_record.gemspec +42 -0
- data/lib/active_record/connection_adapters/elasticsearch/column.rb +20 -6
- data/lib/active_record/connection_adapters/elasticsearch/database_statements.rb +142 -125
- data/lib/active_record/connection_adapters/elasticsearch/quoting.rb +2 -23
- data/lib/active_record/connection_adapters/elasticsearch/schema_creation.rb +30 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb +103 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb +42 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +158 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb +32 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +132 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb +110 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +136 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +174 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +37 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +110 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +398 -174
- data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +232 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb +2 -0
- data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +32 -0
- data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +112 -19
- data/lib/arel/collectors/elasticsearch_query.rb +0 -1
- data/lib/arel/visitors/elasticsearch.rb +7 -579
- data/lib/arel/visitors/elasticsearch_base.rb +234 -0
- data/lib/arel/visitors/elasticsearch_query.rb +463 -0
- data/lib/arel/visitors/elasticsearch_schema.rb +124 -0
- data/lib/elasticsearch_record/core.rb +44 -10
- data/lib/elasticsearch_record/errors.rb +13 -0
- data/lib/elasticsearch_record/gem_version.rb +6 -2
- data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +27 -9
- data/lib/elasticsearch_record/model_schema.rb +5 -0
- data/lib/elasticsearch_record/persistence.rb +31 -26
- data/lib/elasticsearch_record/query.rb +56 -17
- data/lib/elasticsearch_record/querying.rb +17 -0
- data/lib/elasticsearch_record/relation/calculation_methods.rb +3 -0
- data/lib/elasticsearch_record/relation/core_methods.rb +57 -17
- data/lib/elasticsearch_record/relation/query_clause_tree.rb +38 -1
- data/lib/elasticsearch_record/relation/query_methods.rb +6 -0
- data/lib/elasticsearch_record/relation/result_methods.rb +15 -9
- data/lib/elasticsearch_record/result.rb +32 -5
- data/lib/elasticsearch_record/statement_cache.rb +2 -1
- data/lib/elasticsearch_record.rb +2 -2
- metadata +29 -11
- data/.ruby-version +0 -1
- 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
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
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
|
-
|
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
|