2017-01-13 9 views
0

私のRailsプロジェクトでは、プロファイルを特定の基準のセットに合わせる必要があります。現在の設定では、各プロファイルに一連の評価があり、最新の評価が有効な評価です。各評価は、0〜4の値を持つプロパティのセットで構成されています。カスタムの「フィルタ評価」(名前空間は自分のコードにProfessionProfileです)を作成し、最新の評価を持つすべてのプロファイルがより良いか等しい(各プロパティでより大きいか等しい値)をフィルタよりも大きくします。Ruby on Railsのマッチングアルゴリズム

私の現在の解決策は機能しますが、サーバーへの膨大な要求が発生するため、多くの時間がかかります。これを1回のリクエストで実行したいと思います。 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

2番目の解決策では、 'profiles'を' property_values'で直接結合します。これは正しいです?以前のソリューションでは、 'profile'の' property_evaluations'を介して 'property_values'にアクセスし、' profile'を直接経由するのではないので、私は尋ねています。 – larsbe

+0

私はこのプロファイルを使って 'has_many:property_values、::property_evaluations'というプロファイルを指定する必要がありましたが、実際には最新の評価しか得ることができないかどうかは分かりません – Ozgar

答えて

0

私はそれが最終的に動作するように管理しました。解決策はそれほどきれいではありませんが、速くてうまく動作し、2つの重大なクエリしか作成できません。私は、2つの配列の交差を返す配列に対して&演算子を使用して終了しました。また、多くのサーバー通信を必要とする各プロファイル(Profile.each.property_evaluations.order(:created_at))の最新のPropertyEvaluationを見つける必要性を避けるために、PropertyEvaluationsにブール値属性を追加しました。 profile.rbで

:私は最初のIDの配列に変換

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 

理由は、このように、2つのActiveRecordをの交点を取得するためにのみ使用可能だが、レールにマージ()関数は、配列を返すことです、私の状況では私は少なくとも11以上交差する必要があります。

誰かが "railsier"ソリューションを思いつくべきであれば、共有してください!