2017-01-13 77 views
0

在我的Rails項目中,我需要將配置文件與特定的一組條件進行匹配。我目前的設置是每個配置文件都有一組評估,其中最新評估是活動評估。每個評估都包含一組可能具有從0到4的值的屬性。我想創建一個自定義的「過濾器評估」(名稱空間是我的代碼中的ProfessionProfile),並查找所有最新評估的配置文件是更好還是相等(每個屬性的值較高或相等)比過濾器。Ruby on Rails中的匹配算法

我目前的解決方案工作正常,但會向服務器發出大量請求,因此花費了大量時間,我希望在單個請求中執行此操作。 FYI使用PostgreSQL。

目前的解決方案:

filters_controller.rb:

def filter_by_profession(profiles) 
    hits = [] 
    profession = ProfessionProfile.find(params[:profession]) 
    Profile.find_each do |p| 
     if p.has_better_values(profession) 
      hits << p 
     end 
    end 
    profiles = profiles.where(id: hits.map(&:id)) 
end 

profile.rb:

def has_better_values(profession_profile) 
    latest_evaluation = property_evaluations.order(:created_at).first 
    if latest_evaluation.present? 
     latest_evaluation.property_values.each do |value| 
      profession_value = profession_profile.property_values.where(property_id: value.property_id) 
      return false if profession_value.present? && value.value < profession_value.take!.value 
     end 
     return true 
    else 
     return false 
    end 
end 

而不是做這個,我曾嘗試以下解決方案,但它總是返回一個空集,即使我應該有一場比賽。

def filter_by_profession(profiles) 
    profession_profile = ProfessionProfile.find(params[:profession]) 
    profiles = profiles.joins(:property_values) 
    profession_profile.property_values.find_each do |property_value| 
     profiles = profiles 
         .where("property_values.property_id = ?", property_value.property_id) 
         .where("property_values.value >= ? ", property_value.value) 
    end 
    profiles 
end 

任何提示或幫助,將不勝感激!

我看過類似的問題here但我未能適應我的情況。

+0

在第二種解決方案中,您直接使用'property_values'連接'profiles'。它是否正確?我在問,因爲在以前的解決方案中,您通過'profile'的property_evaluations來訪問property_values,而不是直接通過'profile'來訪問。 – larsbe

+0

我應該通過以下方式指定配置文件'has_many:property_values,通過::property_evaluations',但是您正在進行其他操作,通過這樣做我不確定我是否能夠實際上只獲得最新的評估 – Ozgar

回答

0

我終於設法讓它工作。該解決方案不是很漂亮,但速度很快,只需創建兩個嚴重問題即可運行。我最終使用&運算符來返回兩個數組的交集。我還爲PropertyEvaluations添加了布爾屬性,以避免需要爲每個配置文件(Profile.each.property_evaluations.order(:created_at))查找最新的PropertyEvaluation,這需要進行大量的服務器通信。

在profile.rb:

def self.matches_profession(profession_profile) 
    property_values = profession_profile.property_values.pluck(:property_id, :value) 
    ids = Profile.ids 
    property_values.each do |p| 
     ids = ids & PropertyEvaluation.where(current: true) 
      .joins(:property_values) 
      .where("property_values.property_id = ?", p[0]) 
      .where("property_values.value >= ?", p[1]).pluck(:profile_id) 
    end 
    Profile.where(id: ids) 
end 

我之所以首先被轉換爲ID的數組是,在導軌中的合併()函數返回一個數組,因而它是隻爲獲得兩個ActiveRecords的交叉使用,而在我的情況下,我需要至少相交11.

如果有人應該想出一個「railsier」解決方案,請分享!