Rails:ActiveRecord db排序操作不区分大小写

时间:2012-08-04 04:54:12

标签: sql ruby-on-rails activerecord

我正在尝试学习rails [通过遵循课程中的SAAS课程]并使用ActiveRecord处理简单的Movie表。

我想要显示所有已分类标题的电影。我希望它不区分大小写。

我试过这样做:

Movie.all(:conditions => ["lower(title) = ?", title.downcase],:order => "title DESC")
=>undefined local variable or method `title' for #<MoviesController:0xb4da9a8>

我认为它不承认较低(标题)。

这是实现案件分类排序的最佳方法吗?

谢谢!

4 个答案:

答案 0 :(得分:17)

使用where而非all

Movie.where("lower(title) = ?", title.downcase).order("title DESC")

不过真的不明白。在这里,您将获得所有低于标题的电影等于title.downcase。一切都是平等的,你怎么能按title desc排序呢?

按小写标题反向按字母顺序排序所有电影:

Movie.order("lower(title) DESC").all

答案 1 :(得分:6)

你必须这样做:

Movie.order("lower(title) DESC").all

答案 2 :(得分:3)

每次MySQL执行大写或小写操作都非常昂贵。

我建议使用title列和title_lower列。通过这种方式,您可以在title_lower列上轻松显示和排序不区分大小写,而不会在每次排序时执行上限或下限。

请记住将两者或至少title_lower编入索引。

答案 3 :(得分:1)

更强大的解决方案是使用arel节点。我建议在Movie模型上定义几个范围:

scope :order_by_title, -> {
  order(arel_table['title'].lower.desc)
}

scope :for_title, (title)-> {
  where(arel_table['title'].lower.eq title.downcase)
}

然后拨打Movie.for_title(title).order_by_title

与列出的其他答案相比,优势在于.for_title.order_by_title如果您为title列设置别名或加入另一个包含title列的表格,则不会中断,他们是sql转义。

与rickypai mentioned一样,如果列上没有索引,则数据库速度会很慢。但是,复制数据并将转换应用于另一列是不正常的(正常)形式,因为一列可能与另一列不同步。不幸的是,早期版本的mysql不允许除触发器之外的许多alternatives。在5.7.5之后,您可以使用虚拟generated columns来执行此操作。然后在不区分大小写的情况下,您只需使用生成的列(这实际上使得ruby更直接)。

Postgres在这方面有更多的灵活性,可以让你在不需要引用特殊列的情况下为函数创建索引,或者可以使列不区分大小写。