![](/img/trans.png)
[英]'in' and 'not in' counts do not add up - what's wrong?
[英]What's the right way to do counts in Rails?
我有一個 Rails 應用程序,其中包含許多以下代碼:
Our active community of <%= Account.find_all_by_admin(false).count %>
我的問題是,這是對視圖進行計數的正確方法嗎? 看起來如此“骯臟”有沒有更荒謬的計數方法? 我可能在考慮命名范圍,但我只想確保這些類型的東西不會對性能產生更大的影響。
謝謝你,
您不需要名稱范圍來執行計數。
Account.where(:admin => false).count
但是命名范圍是使代碼更可重用的極好方法。
命名范圍對您的應用程序沒有任何明顯的性能影響。
我建議你避免在我的模板中直接訪問數據庫,因為那樣你會在緩存方面失去一些靈活性。
嘗試准備您需要在操作中呈現的所有數據,然后使用有意義的實例變量,例如@number_of_accounts
或@accounts.count
。
如果您以不同的格式(html、json 等)呈現動作,這將使您的視圖更清晰、更易於調試,並且也會更 DRY
至於你如何得到你的數字 - 它並不那么重要,只是從 find_* 方法轉向范圍和編寫可讀的代碼
在 rails 3 中,一個簡單的 count 調用會發出一個簡單的 count 請求:
Contact.count
被解析為:
SELECT COUNT(*) AS count_id FROM "contacts"
find all by field name 將解析為:
Contact.find_all_by_country("Canada")
SELECT "contacts".* FROM "contacts" WHERE ("contacts"."country" = 'Canada')
我建議為您的管理列建立索引以加快查找速度,這可以轉換為命名范圍,但它本身只會預定義查詢,而不是優化它。
重要的是要注意,如果您發出
Contact.find_all_by_country("Canada").count
count
是數組類上的一個方法,實際上並不對數據庫發出計數:
Contact.find_all_by_country("Canada").count
SELECT "contacts".* FROM "contacts" WHERE ("contacts"."country" = 'Canada')
命名范圍不應影響性能
scope :not_admin, where(:admin => false)
然后你可以有Account.not_admin.count
根據 DGM 的評論進行編輯:要在控制台中檢查生成的 SQL, Account.find_all_by_admin(false).to_sql
Account.not_admin.to_sql
與Account.find_all_by_admin(false).to_sql
進行比較
您可以使用以下查詢代替Account.where(:admin => false).count
Account.select(:id).where(:admin => false).count
只需選擇一列,而不是選擇全部。 它生成以下查詢,並且比前一個查詢更快:
SELECT COUNT("accounts"."id") FROM "accounts" where admin = false
您應該在控制器中創建一個instance variable
並在視圖中使用它。 這會讓你看得清楚。
@accounts_count = Account.where(admin: false).count
並在視圖中使用它,如 `<%= @accounts_count %>
如果要循環遍歷結果和計數,可以使用以下方式:
@accounts = Account.where(admin: false)
鑒於,寫如下:
<%= @accounts.count %>
// For looping account
<% @accounts.each do |account| %>
# do some stuff
<% end %>
但上述方式將觸發 2 個查詢,1 個用於計數,另一個用於循環。
正確的做法
使用size
而不是count
。 它將觸發 1 個查詢,但您需要更改視圖中的計數順序,例如:
// For looping account
<% @accounts.each do |account| %>
# do some stuff
<% end %>
<%= @accounts.size %>
如果你想要相同的順序,那么首先加載用戶對象,如下所示
<%= @accounts.load.size %>
// For looping account
<% @accounts.each do |account| %>
# do some stuff
<% end %>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.