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

Sve*_*ven 10 database indexing activerecord ruby-on-rails

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

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

class Book < ActiveRecord::Base
  default_scope :order => 'lower(title) DESC'
end
Run Code Online (Sandbox Code Playgroud)

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

CREATE INDEX lowercase_book_title_index ON book (lower(title));
Run Code Online (Sandbox Code Playgroud)

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

CREATE INDEX lowercase_book_title_index ON book (title COLLATE NOCASE);
Run Code Online (Sandbox Code Playgroud)

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

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

add_index :books, :title
Run Code Online (Sandbox Code Playgroud)

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

mor*_*itz 0

我从来没有遇到过这种排序的问题。基本上,您想要的结果是这样排序的:

"A bad title"
"A better title"
"a good title"
"An excellent title"
Run Code Online (Sandbox Code Playgroud)

如果这是正确的并且您要使用 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
Run Code Online (Sandbox Code Playgroud)

utf8_general_ci 的意思是“以独立于语言的方式与 utf8 进行比较,并且不区分大小写”。

这应该可以解决问题。