2017-06-06 38 views
0

我想用類似如下的WHERE子句來查詢從數據庫中的一些對象:如何禁用活動記錄查詢的延遲加載?

@monuments = Monument.where("... lots of SQL ...").limit(6) 

後來,在我看來,我用像@monuments.first方法,然後我遍歷@monuments,然後我展示@monuments.count

當我查看Rails控制檯時,發現Rails多次查詢數據庫,首先限制爲1(對於@monuments.first),然後限制爲6(對所有數據進行循環),最後它發出一個count()查詢。

我該如何告訴ActiveRecord只執行一次查詢?只需執行一次限制爲6的查詢就足以獲得我需要的所有數據。由於查詢速度很慢(80ms),因此重複它會花費很多時間。

回答

1

在你的情況下,你需要在你調用first之前觸發查詢,因爲雖然firstArray上的一種方法,但它也是ActiveRecord對象上的「查找方法」我們將獲取第一條記錄。

您可以使用任何需要數據處理的方法來提示。我更喜歡使用to_a,因爲很顯然,我們將用一個陣列後處理:

@moments = Moment.where(foo: true).to_a 
# SQL Query Executed 
@moments.first #=> (Array#first) <Moment @foo=true> 
@moments.count #=> (Array#count) 42 

在這種情況下,也可以替代使用first(6)limit(6),這也將觸發查詢。然而,您的團隊中的其他開發人員可能不太明顯這是故意的。

1

AFAIK,@monuments.first不應該擊中數據庫,我確認它在我的控制檯上,也許你有多個具有相同變量的實例或者你正在做其他事情(你沒有在這裏共享),分享確切的代碼和查詢我們可能會調試。

因爲,ActiveRecord Collections作爲數組,您可以使用數組類比來避免查詢數據庫。

關於first你可以做,

@monuments[0] 

關於count,是的,這是一個不同的查詢其打分貝,以避免它,你可以使用length作爲..

@monuments.length 
+0

這裏有很多猜想,不持有水。您可能想查看優秀的[Rails ActiveRecord查詢指南](http://guides.rubyonrails.org/active_record_querying.html)。 – coreyward

+0

我可能沒有能夠更好地解釋,但我非常確定,即使沒有'.to_a'和'.first'沒有命中db,OP詢問的類型的where查詢也會被執行。事實上,使用'.to_a'首先有很多缺點,當你轉換爲array時,你不能執行作用域查詢或任何其他與AR有關的方法。其次,正如你所提到的那樣,它會在以後讓開發者感到困惑。第三,'.count'命中db不是因爲它並沒有被第一個執行,而是一個作用域查詢並且改變了實際查詢的定義,即'@ monuments' .. –

+0

如果你能想出一個例如,一個查詢不是先執行,而是在'to_a'之後執行,並且當'.first'被追加時,它會再次執行db .. –