Module: ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaStatements
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/active_record/connection_adapters/elasticsearch/schema_statements.rb
Overview
extend adapter with schema-related statements
ORIGINAL methods untouched:
- internal_string_options_for_primary_key
- options_include_default?
- fetch_type_metadata
- column_exists?
SUPPORTED but not used:
- strip_table_name_prefix_and_suffix
UNSUPPORTED methods that will be +ignored+:
- native_database_types
- table_options
- table_comment
- table_alias_for
- columns_for_distinct
- extract_new_default_value
- insert_versions_sql
- data_source_sql
- quoted_scope
- add_column_for_alter
- rename_column_sql
- remove_column_for_alter
- remove_columns_for_alter
- add_timestamps_for_alter
- remove_timestamps_for_alter
- foreign_key_name
- foreign_key_for
- foreign_key_for!
- extract_foreign_key_action
- check_constraint_name
- check_constraint_for
- check_constraint_for!
- validate_index_length!
- can_remove_index_by_name?
- index_column_names
- index_name_options
- add_index_sort_order
- options_for_index_columns
- add_options_for_index_columns
- index_name_for_remove
- add_index_options
- index_algorithm
- quoted_columns_for_index
- check_constraint_options
- check_constraints
- foreign_key_exists?
- foreign_key_column_for
- foreign_key_options
- foreign_keys
- index_name_exists?
- indexes
- index_name
- index_exists?
UNSUPPORTED methods that will +fail+:
- views
- view_exists?
- add_index
- remove_index
- rename_index
- add_reference
- remove_reference
- add_foreign_key
- remove_foreign_key
- add_check_constraint
- remove_check_constraint
- rename_table_indexes
- rename_column_indexes
- create_alter_table
- insert_fixture
- insert_fixtures_set
- bulk_change_table
- dump_schema_information
OVERWRITTEN methods for Elasticsearch: ...
Instance Method Summary collapse
-
#access_id_fielddata? ⇒ Boolean
returns true if the cluster option 'id_field_data' is enabled or not configured.
-
#access_shard_doc? ⇒ Boolean
returns true if +_shard_doc+ field can be accessed through PIT-search.
-
#alias_exists?(table_name, alias_name) ⇒ Boolean
Checks to see if a alias +alias_name+ within a table +table_name+ exists on the database.
- #assume_migrated_upto_version(version) ⇒ Object
- #clone_table_definition(name, target, **options) ⇒ Object
-
#cluster_health(**options) ⇒ Hash
returns the cluster health.
-
#cluster_info ⇒ Hash{Symbol->Unknown
Returns basic information about the cluster.
-
#cluster_settings ⇒ Hash
returns a hash of current set, none-default settings in flat.
-
#column_definitions(table_name) ⇒ Array<Hash>
Returns the list of a table's column names, data types, and default values.
-
#create_schema_dumper(options) ⇒ Object
overwrite original methods to provide a elasticsearch version.
-
#create_table_definition(name, **options) ⇒ Object
overwrite original methods to provide a elasticsearch version.
-
#data_source_exists?(name) ⇒ Boolean
Checks to see if the data source +name+ exists on the database.
-
#data_sources ⇒ Array<String>
Returns the relation names usable to back Active Record models.
-
#lookup_cast_type_from_column(column) ⇒ ActiveRecord::ConnectionAdapters::Elasticsearch::Type::MulticastValue
lookups from building the @columns_hash.
-
#mapping_exists?(table_name, mapping_name, type = nil) ⇒ Boolean
Checks to see if a mapping +mapping_name+ within a table +table_name+ exists on the database.
-
#max_result_window(table_name) ⇒ Integer
returns the maximum allowed size for queries for the provided +table_name+.
-
#meta_exists?(table_name, meta_name) ⇒ Boolean
Checks to see if a meta +meta_name+ within a table +table_name+ exists on the database.
-
#new_column_from_field(_table_name, field) ⇒ ActiveRecord::ConnectionAdapters::Column
creates a new column object from provided field Hash.
-
#primary_keys(table_name) ⇒ Object
Returns a array of tables primary keys.
-
#schema_creation ⇒ Object
overwrite original methods to provide a elasticsearch version.
-
#setting_exists?(table_name, setting_name) ⇒ Boolean
Checks to see if a setting +setting_name+ within a table +table_name+ exists on the database.
-
#table_aliases(table_name) ⇒ Hash
returns a hash of all aliases by provided table_name (index).
-
#table_exists?(table_name) ⇒ Boolean
Checks to see if the table +table_name+ exists on the database.
-
#table_mappings(table_name) ⇒ Hash
returns a hash of all mappings by provided table_name (index).
-
#table_metas(table_name) ⇒ Hash
returns a hash of all meta data by provided table_name (index).
-
#table_schema(table_name, features = [:aliases, :mappings, :settings]) ⇒ Hash
returns a hash of the full definition of the provided table_name (index).
-
#table_settings(table_name, flat_settings = true) ⇒ Hash
returns a hash of all settings by provided table_name.
-
#table_state(table_name) ⇒ Hash
returns information about number of primaries and replicas, document counts, disk size, ...
-
#tables ⇒ Array<String>
Returns an array of table names defined in the database.
-
#type_to_sql(type) ⇒ Object
transforms provided schema-type to a sql-type overwrite original methods to provide a elasticsearch version.
-
#update_table_definition(name, base = self, **options) ⇒ Object
overwrite original methods to provide a elasticsearch version.
Instance Method Details
#access_id_fielddata? ⇒ Boolean
returns true if the cluster option 'id_field_data' is enabled or not configured. This is required to check if a general sorting on the +_id+-field is possible or not.
367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 367 def access_id_fielddata? @access_id_fielddata = begin status = self.cluster_settings['indices.id_field_data.enabled'] # for cluster version lower 7.6 this might not configured. status = (cluster_info[:version] < "7.6") if status.nil? status end if @access_id_fielddata.nil? @access_id_fielddata end |
#access_shard_doc? ⇒ Boolean
returns true if +_shard_doc+ field can be accessed through PIT-search.
381 382 383 384 385 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 381 def access_shard_doc? @access_shard_doc = cluster_info[:version] >= "7.12" if @access_shard_doc.nil? @access_shard_doc end |
#alias_exists?(table_name, alias_name) ⇒ Boolean
Checks to see if a alias +alias_name+ within a table +table_name+ exists on the database.
alias_exists?(:developers, 'my-alias')
295 296 297 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 295 def alias_exists?(table_name, alias_name) table_aliases(table_name).keys.include?(alias_name.to_s) end |
#assume_migrated_upto_version(version) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 94 def assume_migrated_upto_version(version) version = version.to_i migrated = migration_context.get_all_versions versions = migration_context.migrations.map(&:version) unless migrated.include?(version) # use a ActiveRecord syntax to create a new version schema_migration.create(version: version) end inserting = (versions - migrated).select { |v| v < version } if inserting.any? if (duplicate = inserting.detect { |v| inserting.count(v) > 1 }) raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict." end # use a ActiveRecord syntax to create new versions inserting.each { |iversion| schema_migration.create(version: iversion) } end true end |
#clone_table_definition(name, target, **options) ⇒ Object
348 349 350 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 348 def clone_table_definition(name, target, **) ::ActiveRecord::ConnectionAdapters::Elasticsearch::CloneTableDefinition.new(self, name, target, **) end |
#cluster_health(**options) ⇒ Hash
returns the cluster health
412 413 414 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 412 def cluster_health(**) api(:cluster, :health, , 'CLUSTER HEALTH').to_h end |
#cluster_info ⇒ Hash{Symbol->Unknown
Returns basic information about the cluster.
389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 389 def cluster_info @cluster_info ||= begin response = api(:core, :info, {}, 'CLUSTER INFO') { name: response.dig('name'), cluster_name: response.dig('cluster_name'), cluster_uuid: response.dig('cluster_uuid'), version: Gem::Version.new(response.dig('version', 'number')), lucene_version: response.dig('version', 'lucene_version') } end end |
#cluster_settings ⇒ Hash
returns a hash of current set, none-default settings in flat
405 406 407 408 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 405 def cluster_settings settings = api(:cluster, :get_settings, { flat_settings: true }, 'CLUSTER SETTINGS') settings['persistent'].merge(settings['transient']) end |
#column_definitions(table_name) ⇒ Array<Hash>
Returns the list of a table's column names, data types, and default values.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 198 def column_definitions(table_name) mappings = table_mappings(table_name) # prevent exceptions on missing mappings, to provide the possibility to create them # otherwise loading the table (index) will always fail! mappings = { 'properties' => {} } if mappings.blank? || mappings['properties'].blank? # raise(ActiveRecord::StatementInvalid, "Could not find valid mappings for '#{table_name}'") if mappings.blank? || mappings['properties'].blank? # since the received mappings do not have the "primary" +_id+-column we manually need to add this here # The BASE_STRUCTURE will also include some meta keys like '_score', '_type', ... ActiveRecord::ConnectionAdapters::ElasticsearchAdapter::BASE_STRUCTURE + mappings['properties'].map { |key, prop| # resolve (nested) fields and properties fields, properties = resolve_fields_and_properties(key, prop, true) # fallback for possible empty type type = prop['type'].presence || (properties.present? ? 'object' : 'nested') # return a new hash prop.merge('name' => key, 'type' => type, 'fields' => fields, 'properties' => properties) } end |
#create_schema_dumper(options) ⇒ Object
overwrite original methods to provide a elasticsearch version
334 335 336 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 334 def create_schema_dumper() ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaDumper.create(self, ) end |
#create_table_definition(name, **options) ⇒ Object
overwrite original methods to provide a elasticsearch version
339 340 341 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 339 def create_table_definition(name, **) ::ActiveRecord::ConnectionAdapters::Elasticsearch::CreateTableDefinition.new(self, name, **) end |
#data_source_exists?(name) ⇒ Boolean
Checks to see if the data source +name+ exists on the database.
data_source_exists?(:ebooks)
271 272 273 274 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 271 def data_source_exists?(name) # response returns boolean api(:indices, :exists?, { index: name, expand_wildcards: [:open, :closed] }, 'SCHEMA') end |
#data_sources ⇒ Array<String>
Returns the relation names usable to back Active Record models. For Elasticsearch this means all indices - which also includes system +dot+ '.' indices.
121 122 123 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 121 def data_sources api(:indices, :get, { index: :_all, expand_wildcards: [:open, :closed] }, 'SCHEMA').keys end |
#lookup_cast_type_from_column(column) ⇒ ActiveRecord::ConnectionAdapters::Elasticsearch::Type::MulticastValue
lookups from building the @columns_hash. since Elasticsearch has the "feature" to provide multicast values on any type, we need to fetch them ... you know, ES can return an integer or an array of integers for any column ...
244 245 246 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 244 def lookup_cast_type_from_column(column) type_map.lookup(:multicast_value, super) end |
#mapping_exists?(table_name, mapping_name, type = nil) ⇒ Boolean
Checks to see if a mapping +mapping_name+ within a table +table_name+ exists on the database.
mapping_exists?(:developers, :status, :integer)
318 319 320 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 318 def mapping_exists?(table_name, mapping_name, type = nil) column_exists?(table_name, mapping_name, type) end |
#max_result_window(table_name) ⇒ Integer
returns the maximum allowed size for queries for the provided +table_name+. The query will raise an ActiveRecord::StatementInvalid if the requested limit is above this value.
360 361 362 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 360 def max_result_window(table_name) table_settings(table_name).dig('index', 'max_result_window').presence || 10000 end |
#meta_exists?(table_name, meta_name) ⇒ Boolean
Checks to see if a meta +meta_name+ within a table +table_name+ exists on the database.
meta_exists?(:developers, 'class')
329 330 331 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 329 def (table_name, ) (table_name).keys.include?(.to_s) end |
#new_column_from_field(_table_name, field) ⇒ ActiveRecord::ConnectionAdapters::Column
creates a new column object from provided field Hash
226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 226 def new_column_from_field(_table_name, field) ActiveRecord::ConnectionAdapters::Elasticsearch::Column.new( field["name"], field["null_value"], (field["type"]), meta: field['meta'], virtual: field['virtual'], fields: field['fields'], properties: field['properties'], enabled: field['enabled'] ) end |
#primary_keys(table_name) ⇒ Object
Returns a array of tables primary keys. PLEASE NOTE: Elasticsearch does not have a concept of primary key. The only thing that uniquely identifies a document is the index together with the +_id+. To support this concept we simulate this through the +_meta+ field (from the index).
As a alternative, the primary_key can also be provided through the mappings +meta+ field.
see @ https://www.elastic.co/guide/en/elasticsearch/reference/8.5/mapping-meta-field.html
258 259 260 261 262 263 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 258 def primary_keys(table_name) (table_name).dig('primary_key').presence || column_definitions(table_name). select { |f| f['meta'] && f['meta']['primary_key'] == 'true' }. # only take the last found primary key (if no custom primary_key was provided this will return +_id+ ) map { |f| f["name"] }[-1..-1] end |
#schema_creation ⇒ Object
overwrite original methods to provide a elasticsearch version
353 354 355 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 353 def schema_creation ::ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaCreation.new(self) end |
#setting_exists?(table_name, setting_name) ⇒ Boolean
Checks to see if a setting +setting_name+ within a table +table_name+ exists on the database. The provided +setting_name+ must be flat!
setting_exists?(:developers, 'index.number_of_replicas')
307 308 309 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 307 def setting_exists?(table_name, setting_name) table_settings(table_name).keys.include?(setting_name.to_s) end |
#table_aliases(table_name) ⇒ Hash
returns a hash of all aliases by provided table_name (index).
159 160 161 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 159 def table_aliases(table_name) api(:indices, :get_alias, { index: table_name, expand_wildcards: [:open, :closed] }, 'SCHEMA').dig(table_name, 'aliases') end |
#table_exists?(table_name) ⇒ Boolean
Checks to see if the table +table_name+ exists on the database.
table_exists?(:developers)
283 284 285 286 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 283 def table_exists?(table_name) # just reference to the data sources data_source_exists?(table_name) end |
#table_mappings(table_name) ⇒ Hash
returns a hash of all mappings by provided table_name (index)
136 137 138 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 136 def table_mappings(table_name) api(:indices, :get_mapping, { index: table_name, expand_wildcards: [:open, :closed] }, 'SCHEMA').dig(table_name, 'mappings') end |
#table_metas(table_name) ⇒ Hash
returns a hash of all meta data by provided table_name (index). HINT: +_meta+ is resolved from the table mappings
144 145 146 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 144 def (table_name) table_mappings(table_name).dig('_meta').presence || {} end |
#table_schema(table_name, features = [:aliases, :mappings, :settings]) ⇒ Hash
returns a hash of the full definition of the provided table_name (index). (includes settings, mappings & aliases)
179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 179 def table_schema(table_name, features = [:aliases, :mappings, :settings]) if cluster_info[:version] >= '8.5.0' response = api(:indices, :get, { index: table_name, expand_wildcards: [:open, :closed], features: features, flat_settings: true }, 'SCHEMA') else response = api(:indices, :get, { index: table_name, expand_wildcards: [:open, :closed], flat_settings: true }, 'SCHEMA') end { settings: response.dig(table_name, 'settings'), mappings: response.dig(table_name, 'mappings'), aliases: response.dig(table_name, 'aliases') } end |
#table_settings(table_name, flat_settings = true) ⇒ Hash
returns a hash of all settings by provided table_name
152 153 154 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 152 def table_settings(table_name, flat_settings = true) api(:indices, :get_settings, { index: table_name, expand_wildcards: [:open, :closed], flat_settings: flat_settings }, 'SCHEMA').dig(table_name, 'settings') end |
#table_state(table_name) ⇒ Hash
returns information about number of primaries and replicas, document counts, disk size, ... by provided table_name (index).
166 167 168 169 170 171 172 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 166 def table_state(table_name) response = api(:cat, :indices, { index: table_name, expand_wildcards: [:open, :closed] }, 'SCHEMA') [:health, :status, :name, :uuid, :pri, :rep, :docs_count, :docs_deleted, :store_size, :pri_store_size].zip( response.body.split(' ') ).to_h end |
#tables ⇒ Array<String>
Returns an array of table names defined in the database. For Elasticsearch this means all normal indices (no system +dot+ '.' indices)
129 130 131 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 129 def tables data_sources.reject { |key| key[0] == '.' } end |
#type_to_sql(type) ⇒ Object
transforms provided schema-type to a sql-type overwrite original methods to provide a elasticsearch version
419 420 421 422 423 424 425 426 427 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 419 def type_to_sql(type, **) return '' if type.blank? if (native = native_database_types[type.to_sym]) (native.is_a?(Hash) ? native[:name] : native).dup else type.to_s end end |
#update_table_definition(name, base = self, **options) ⇒ Object
overwrite original methods to provide a elasticsearch version
344 345 346 |
# File 'lib/active_record/connection_adapters/elasticsearch/schema_statements.rb', line 344 def update_table_definition(name, base = self, **) ::ActiveRecord::ConnectionAdapters::Elasticsearch::UpdateTableDefinition.new(base, name, **) end |