我在PostgreSQL 9.3.4
和Rails 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
通过psql
验证结果:
psql=# \d photos
...
tags | text[] | not null default '{}'::text[]
Indexes:
"index_photos_on_tags" btree (tags)
请注意,“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
请注意还有另一个问题!
事实证明,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
行中删除add_index
。
答案 0 :(得分:4)
正如paxer所提到的,您需要通过在:sql
中添加(或更改)此行来将架构格式设置为config/application.rb
:
config.active_record.schema_format = :sql
正如Rails Migrations guide中所解释的那样,原因是GIN索引特定于Postgres。当您使用特定于数据库的项目时,schema.rb
将无法重新创建它们。
以下是Rails指南的引用:
但是需要权衡:db / schema.rb无法表示特定于数据库的项目,例如触发器或存储过程。在迁移中,您可以执行自定义SQL语句,但架构转储程序无法从数据库重新构建这些语句。如果您使用这样的功能,那么您应该将架构格式设置为:sql。
使用:sql
格式后,您的架构现在将保存到structure.sql
而不是schema.rb
。这两个文件可以并排生效,但当您的格式设置为structure.sql
时,应用只会:sql
更新并使用{{1}}。