Rails:ActiveRecord数据库排序操作不区分大小写



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

我想显示所有按标题排序的电影。我希望它能被无意识地分类。

我试着这样做:

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

我认为它不承认较低的(头衔)。

这是实现案例独立排序的最佳方式吗?

谢谢!

使用where而非all

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

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

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

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

你必须这样做:

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

一个更健壮的解决方案是使用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提到的那样,如果列上没有索引,那么数据库就会很慢。然而,复制数据并将转换应用于另一列是不好的(正常)形式,因为这样一列可能会与另一列不同步。不幸的是,mysql的早期版本不允许使用触发器以外的其他选项。5.7.5之后,您可以使用虚拟生成的列来执行此操作。然后,在不区分大小写的情况下,只使用生成的列(这实际上使ruby更直接)。

Postgres在这方面有更大的灵活性,它将允许您在不必引用特殊列的情况下对函数进行索引,或者您可以将该列设置为不区分大小写的列。

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

我建议使用title列和title_lower列。这样,您就可以在title_lower列上不区分大小写地轻松显示和排序,而无需每次排序都让MySQL执行上下操作。

请记住同时索引或至少索引title_lower