繁体   English   中英

Ruby on Rails ActiveRecord 中的 Order 和 sort_by 差异

[英]Order and sort_by difference in Ruby on Rails ActiveRecord

我正在尝试根据控制器中的时间戳字段对数据进行排序,请注意时间戳字段可能为空并且可能具有某些值。 我写了以下查询。

@item = Item.sort_by(&:item_timestamp).reverse
            .paginate(:page => params[:page], :per_page =>5)

但是,当我有 time_timestamp 字段值为 NULL 的项目时,这会出错,但以下查询有效。

@item = Item.order(:item_timestamp).reverse
            .paginate(:page => params[:page], :per_page => 5)

谁能说出这两个查询之间的区别,以及在哪种情况下使用哪个?

我正在使用 order 和 reverse 从数据库中获取最新项目,这是最好的方法还是有其他最佳方法可以从性能方面从数据库获取最新数据?

sort_by是在 Ruby 中执行的,所以如果你有一个nil值,事情会以类似的方式中断:

[3, nil, 1].sort
#=> ArgumentError: comparison of Fixnum with nil failed

order由您的 RDBMS 执行,它通常可以处理NULL值。 您甚至可以通过在ORDER BY子句中添加NULL FIRST (通常是默认值)或NULL LAST来指定要放置NULL VALUES

.sort_byEnumerable中的一种 Ruby 方法,用于对数组(或类似数组的对象)进行排序。 使用.sort_by将导致所有记录从数据库加载到服务器内存中,这可能导致严重的性能问题(以及您的 nil 值问题)。

.order是一个 ActiveRecord 方法,它将ORDER BY子句添加到 SQL select 语句中。 数据库将处理对记录的排序。 这在 99% 的情况下是可取的。

嘿,你不需要在那个查询中排序,它会工作很长时间,如果你使用数据库,你应该总是使用:order ,你的问题有解决方案

@item = Item.order('item_timestamp DESC NULLS LAST').paginate(:page => params[:page], :per_page => 5)

正如我之前所说,.order 更快,在大多数情况下就足够了,但有时您需要 sort_by,例如,如果您想按关系中的值排序。

如果您有一个帖子表和一个 view_counters 表,其中包含按文章的查看次数,则无法使用 .order 轻松按总查看次数对帖子进行排序。

但是使用 sort_by,你可以这样做:

posts = @user.posts.joins(:view_counter)
@posts = posts.sort_by { |p| p.total_views }

.sort_by 去浏览每一个元素,得到关系值,然后按照这个关系的值排序,只需要一行代码。

您可以使用&:[attributeName]进一步减少代码,例如:

@posts = posts.sort_by(&:total_views)

另外,对于您关于反向的最后一个问题,您可以这样做:

Item.order(item_timestamp: :desc)

当您使用sort_by您会破坏活动记录缓存,并且如前所述,您将所有记录加载到 RAM 内存中。

在写下查询时,请始终考虑 SQL 和内存世界,它们是 2 件独立的事情。 这就像拥有一个存档 (SQL) 和购物车 (Memory),您可以在其中放置从存档中取出的文件以供以后使用。

正如大多数人提到的,主要区别在于 sort_by 是一种 Ruby 方法,而 order 是 Rails ActiveRecord 方法。 但是,使用它们的场景可能因情况而异。 例如,如果您已经从数据库中检索了数据并希望对加载的数据进行排序,那么您可能会遇到 sort_by 可能适用的场景。 如果您使用 order on 那么您可能会引入 n+1 问题并在您已经加载数据时再次转到数据库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM