首页 文章

是否可以通过Rails / ActiveRecord迁移添加基于函数的数据库无关索引?

提问于
浏览
10

我有一个像这样的ActiveRecord模型:

create_table "books" do |t|
  t.string "title"
end

class Book < ActiveRecord::Base
  default_scope :order => 'lower(title) DESC'
end

正如您所看到的,我想按 title 属性的小写形式排序,但这会在数据库级别上造成性能损失 . 可以使用不同的数据库以不同的方式纠正此命中 . 例如,在PostgreSQL或Oracle中,您可以创建基于函数的索引:

CREATE INDEX lowercase_book_title_index ON book (lower(title));

SQLite3没有基于函数的索引,因此您必须指定排序规则:

CREATE INDEX lowercase_book_title_index ON book (title COLLATE NOCASE);

我没有研究过你是如何用MySQL做的,但我确定有一种方法(整理?虚拟列?) .

无论如何,我希望以正确的Rails方式进行数据库无关的迁移 . 我当然可以创建一个这样的简单索引:

add_index :books, :title

但是这个生成的索引区分大小写 . 我意识到我可以编写一个依赖于数据库的迁移,但它不是很优雅 . 它也不实用 - 我经常发现自己在我的开发工作站上使用SQLite3,在 生产环境 中使用PostgreSQL . add_index的可用选项处理索引名称,唯一性和长度 . 我是否忽略了一种方法来完成我在这里要做的事情?

2 回答

  • 1

    简答:不是

    答案很长:不是,因为并非所有数据库引擎都支持它支持Rails,或者以一种非常不同的方式 . 如果您确定所有数据库引擎都支持它,那么请为ActiveRecord开发人员提交功能请求 .

    请记住:在ActiveRecord迁移中,您只能执行所有数据库引擎支持的操作,特定于数据库的内容需要从迁移中分离初始化 .

    我建议从db:migrate之后运行的独立rake任务设置此归类 . 在我更大的应用程序中,我使用 rake setup ,我可以执行此特定步骤 .

  • 0

    我从未对这种排序有任何问题 . 基本上,你想要的是结果以这种方式排序:

    "A bad title"
    "A better title"
    "a good title"
    "An excellent title"
    

    如果这是正确的并且您使用的是mysql,则可以在database.yml中指定排序规则,尝试:

    production:
      adapter: mysql2 # or mysql for rails < 3
      host: ...
      database: ...
      username: ...
      encoding: utf8 # or whatever you are using
      collation: utf8_general_ci # or whatever fits your language and encoding
    

    utf8_general_ci的意思是“以与语言无关的方式与utf8进行整理并且不区分大小写” .

    这应该可以解决问题 .

相关问题