Функциональные индексы Rails Postgres
Как мне ввести многоцветные индексы, которые содержат функции в schema.rb?
например, это НЕ работает:
add_index "temporary_events", ["templateinfoid", "campaign", "date(gw_out_time)", "messagetype"], :name => "temporary_events_campaign_tinfoid_date_messagetype"
rake db: test: load
rake aborted!
PGError: ERROR: столбец "date (gw_out_time)" не существует
: CREATE INDEX "tempor_events_campaign_tinfoid_date_messagetype" ВКЛ "временные_венты" ( "templateinfoid", "campaign", "date (gw_out_time", "messagetype" )
Ответы
Ответ 1
Встроенный метод ActiveRecord для создания индексов (add_index
) не поддерживает функции или другие более сложные функции. Вместо этого вы можете использовать execute
для создания индекса с SQL:
execute <<-SQL
CREATE INDEX temporary_events_campaign_tinfoid_date_messagetype
ON temporary_events(templateinfoid, campaign, date(gw_out_time), messagetype);
SQL
Обратите внимание, что использование execute
при миграции может быть проблематичным, если вы не используете формат схемы SQL (config.active_record.schema_format = :sql
). Для получения дополнительной информации найдите schema_format.
Ответ 2
Мне удалось получить функциональные индексы из миграций Rails (3.1.3), удалив пару защитных рельсов!
# lib/functional_indexes.rb
module ActiveRecord
module ConnectionAdapters
module SchemaStatements
#disable quoting of index columns to allow functional indexes (e.g lower(full_name) )
def quoted_columns_for_index(column_names, options = {})
column_names
end
def index_name_for_remove(table_name, options = {})
index_name = index_name(table_name, options)
# disable this error check -- it can't see functional indexes
#unless index_name_exists?(table_name, index_name, true)
# raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
#end
index_name
end
end
end
end
Я должен был создать свои собственные имена индексов:
class AddLowerCaseIndexes < ActiveRecord::Migration
def up
add_index :people, 'lower(full_name)', :name => "index_people_on_lower_full_name"
add_index :people, 'lower(company)', :name => "index_people_on_lower_company"
end
def down
remove_index :people, :name => "index_people_on_lower_full_name"
remove_index :people, :name => "index_people_on_lower_company"
end
end
(Вероятно, вам не нужны кавычки вокруг имен столбцов индекса, если вы не делаете что-то безумное, как помещать пробелы или странные символы в них.)
(Вероятно, вы отлично справляетесь с сообщениями об ошибках postgres при попытке отката несуществующих индексов.)
Ответ 3
Если вы используете pg_power gem (https://github.com/TMXCredit/pg_power),
вы можете сделать это следующим образом:
add_index(:comments, 'dmetaphone(author)', :using => 'gist')