Rails Postgres功能索引

时间:2010-07-16 13:17:55

标签: sql ruby-on-rails postgresql indexing

我应该如何将包含函数的多语言索引输入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“temporary_events_campaign_tinfoid_date_messagetype”ON“temporary_events”(“templateinfoid”,“campaign”,“date(gw_out_time”,“messagetype”)

3 个答案:

答案 0 :(得分:15)

用于创建索引(add_index)的内置ActiveRecord方法不支持函数或任何其他更高级的功能。相反,您可以使用execute使用SQL创建索引:

execute <<-SQL
  CREATE INDEX temporary_events_campaign_tinfoid_date_messagetype
  ON temporary_events(templateinfoid, campaign, date(gw_out_time), messagetype);
SQL

请注意,如果您不使用SQL架构格式(execute),则在迁移中使用config.active_record.schema_format = :sql可能会有问题。有关详细信息,请搜索schema_format

答案 1 :(得分:5)

通过移除一对护栏,我能够通过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错误消息很好。)

答案 2 :(得分:1)

如果您使用的是pg_power gem(https://github.com/TMXCredit/pg_power), 你可以通过以下方式完成:

add_index(:comments, 'dmetaphone(author)', :using => 'gist')
相关问题