簡體   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