为什么使用’gin’的add_index会创建一个’btree’索引呢?

我在PostgreSQL 9.3.4Rails 4.0.4

我添加了一个“标签”列,以及相应的gin索引(或者,至少我要求一个)。

 class AddTagsToPhotos < ActiveRecord::Migration def change add_column :photos, :tags, :text, array: true, null: false, default: [] add_index :photos, :tags, using: 'gin' end end 

通过psqlvalidation结果:

 psql=# \d photos ... tags | text[] | not null default '{}'::text[] Indexes: "index_photos_on_tags" btree (tags) 

请注意,“标签”索引是btree类型 – 而我要求gin

现在手动创建一个索引以显示gin可用:

 psql=# create index index_photos_on_tags2 on photos using gin(tags) ; psql=# \d photos Indexes: "index_photos_on_tags" btree (tags) "index_photos_on_tags2" gin (tags) 

确实, gin是可用的。

目前我正在使用原始SQL的这种解决方法 ,但想知道为什么上面的典型方法失败了:

 class AddTagsToPhotos < ActiveRecord::Migration def up add_column :photos, :tags, :text, array: true, null: false, default: [] ActiveRecord::Base.connection.execute('create index index_photos_on_tags on photos using gin(tags) ;') end def down ActiveRecord::Base.connection.execute('drop index index_photos_on_tags') remove_column :photos, :tags end end 

请注意,还有另一个障碍!

事实certificate, db/schema.rb不会将gin设置为索引类型:

 add_index "photos", ["tags"], :name => "index_photos_on_tags" 

潜在的临时解决方法:

 add_index "photos", ["tags"], :name => "index_photos_on_tags", using: :gin 

警报!

在修复此错误之前,您必须在运行迁移时查看对db/schema.rb更改,因为所有将来的迁移都将using: :gin删除using: :gin来自add_index行的using: :gin

正如paxer所提到的,您需要通过在config/application.rb添加(或更改)此行来将架构格式设置为:sql

 config.active_record.schema_format = :sql 

正如Rails迁移指南中所解释的那样,原因是GIN索引特定于Postgres。 当您使用特定于数据库的项目时, schema.rb将无法重新创建它们。

以下是Rails指南中的引用:

但是需要权衡:db / schema.rb不能表示特定于数据库的项目,例如触发器或存储过程。 在迁移中,您可以执行自定义SQL语句,但架构转储程序无法从数据库重新构建这些语句。 如果您使用这样的function,那么您应该将架构格式设置为:sql。

使用:sql格式后,您的架构现在将保存到structure.sql而不是schema.rb 。 这两个文件可以并排存在,但只有当您的格式设置为:sql时,应用程序才会更新并使用structure.sql