2012-07-26 53 views
3

在我的rails項目中,我有一項功能可以顯示用戶是否有任何Facebook好友已經在該網站上。驗證後,我打開他們的Facebook朋友到@fb_friends然後做到這一點:Rails Active Record:如何減少訪問數據庫的次數?

@fb_friends.each do |friend| 
    friend_find = Authorization.find_by_uid_and_provider(friend[:identifier], 'facebook') 
    if friend_find 
     @fb_friends_on_cody << friend_find.user_id 
     @fb_friends.delete(friend) 
    end 
    end 

基本上,如果發現匹配(通過授權表),我推說記錄@fb_friends_on_cody。這被證明是一個非常昂貴的操作:

  1. 這個命中每個朋友一次數據庫。所以在我的情況下,總共執行了582個查詢。

  2. 每個Authorization.find_by_uid_and_provider的性能都很差。我有添加索引,像這樣:

    ​​

我想了很多的性能增益可以通過解決第一點可以看出。也許有一些方法可以使查詢本身更高效。欣賞這些方面的任何提示。

解決方案

使用Unixmonkey的指導下,我能夠查詢的數量減少,從582到1!下面是最終代碼:

friend_ids = @fb_friends.map{|f| f[:identifier] } 
    authorizations = Authorization.where('provider = ? AND uid IN (?)','facebook',friend_ids) 
    @fb_friends_on_cody = authorizations.map{ |a| { user_id: a.user_id, uid: a.uid }} 
    @fb_friends.reject!{|f| @fb_friends_on_cody.map{|f| f[:uid]}.include?(f[:identifier]) } 

回答

2

我認爲這應該工作

friend_ids = @fb_friends.map(&:id) 
authorizations = Authorization.where('provider = ? AND uid IN (?)','facebook',friend_ids) 
@fb_friends_on_cody = authorizations.map(&:user_id) 
@fb_friends.delete_all('id in (?)', @fb_friends_on_cody) 
+0

啊。你打敗了我。 OP:http://www.w3schools.com/sql/sql_in.asp – joslinm 2012-07-26 20:45:06

+0

謝謝!它不喜歡這行'@ fb_friends.delete_all('(')',@fb_friends_on_cody)''可能是因爲@fb_friends是一個數組(不是ActiveRecord)。我需要爲數組找到一個類似的「delete_all」方法。 – pejmanjohn 2012-07-26 20:50:41

+0

'@ fb_friends.reject!{| f | @ fb_friends_on_cody.include?(f.id)}' – Unixmonkey 2012-07-26 20:53:08