帮助处理具有太多联接的复杂 ActiveRecord 查询

发布于 2024-11-10 04:36:15 字数 1304 浏览 0 评论 0原文

我有以下模型

class User < ActiveRecord::Base
  has_many :occupations,     :dependent => :destroy
  has_many :submitted_jobs,  :class_name => 'Job', :foreign_key => 'customer_id'
  has_many :assigned_jobs,   :class_name => 'Job', :foreign_key => 'employee_id'
end

class Job < ActiveRecord::Base
  belongs_to :customer, :class_name => 'User', :foreign_key => 'customer_id'
  belongs_to :employee, :class_name => 'User', :foreign_key => 'employee_id'
  belongs_to :field
end

class Occupation < ActiveRecord::Base
  belongs_to :user
  belongs_to :field
  belongs_to :expertise
end

以及 Field (仅名称和 id)和 Expertise (名称和整数排名)。

我需要创建一个过滤器,其工作原理类似于以下伪代码。

select * from jobs where employee_id == current_user_id
or employee_id == 0
  and current_user has occupation where occupation.field == job.field
  and if job.customer has occupation where occupation.field == job.field
    current_user.occupations must include an occupation where field == job.field
      and expertise.rank > job.customer.occupation.expertise.rank

您可以看到我如何通过如此复杂的查询快速耗尽我的 SQL 知识。

你会怎么做?正确的 SQL 会很棒,但是如果 Rails 人员可以向我指出使用 ActiveRecord 方法执行此操作的正确方法,那也很棒。或者也许我没有很好地构建我的模型;我愿意接受各种建议。

谢谢!

I have the following models

class User < ActiveRecord::Base
  has_many :occupations,     :dependent => :destroy
  has_many :submitted_jobs,  :class_name => 'Job', :foreign_key => 'customer_id'
  has_many :assigned_jobs,   :class_name => 'Job', :foreign_key => 'employee_id'
end

class Job < ActiveRecord::Base
  belongs_to :customer, :class_name => 'User', :foreign_key => 'customer_id'
  belongs_to :employee, :class_name => 'User', :foreign_key => 'employee_id'
  belongs_to :field
end

class Occupation < ActiveRecord::Base
  belongs_to :user
  belongs_to :field
  belongs_to :expertise
end

along with Field (just name and id) and Expertise (name and integer rank).

I need to create a filter that works like the following pseudocode

select * from jobs where employee_id == current_user_id
or employee_id == 0
  and current_user has occupation where occupation.field == job.field
  and if job.customer has occupation where occupation.field == job.field
    current_user.occupations must include an occupation where field == job.field
      and expertise.rank > job.customer.occupation.expertise.rank

You can see how I quickly exhaust my knowledge of SQL with a query this complex.

How would you do it? The proper SQL would be great, but if a Rails person can point me towards the correct way to do it with ActiveRecord methods, that's great too. Or maybe I'm not structuring my models very well; I'm open to all kinds of suggestions.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾其所爱 2024-11-17 04:36:15

我可能错过了一些东西,并且没有考虑重构模型,但这里有一些东西可能会帮助您获得完整的解决方案或如何重新制定查询

代码未经测试或语法检查

@jobs = Job.
    joins(:employee,:occupation).
    includes(:customer => {:occupations => :expertise}).
    where(:employee_id => current_user.id).
    where("occupations.field_id = jobs.field_id").all

user_occupations = current_user.occupations.include(:expertise)

user_occupations_by_field_id = user_occupations.inject({}) do |hash,oc|
    hash[oc.field_id] = oc
    hash
end

@jobs.reject! do |j|
  common_occupations = j.customer.occupations.select do |oc|
    if c = user_occupations_by_field_id[oc.field_id]
        !user_occupations.select do |eoc|
            c.field_id == eoc.field_id && c.expertise.rank > oc.expertise.rank
        end.empty?
    else
        true
    end
  end

end

I might have missed something and did not look into refactoring the models but heres something that might help you to a complete solution or how to reformulate your query

The code is not tested or syntax checked

@jobs = Job.
    joins(:employee,:occupation).
    includes(:customer => {:occupations => :expertise}).
    where(:employee_id => current_user.id).
    where("occupations.field_id = jobs.field_id").all

user_occupations = current_user.occupations.include(:expertise)

user_occupations_by_field_id = user_occupations.inject({}) do |hash,oc|
    hash[oc.field_id] = oc
    hash
end

@jobs.reject! do |j|
  common_occupations = j.customer.occupations.select do |oc|
    if c = user_occupations_by_field_id[oc.field_id]
        !user_occupations.select do |eoc|
            c.field_id == eoc.field_id && c.expertise.rank > oc.expertise.rank
        end.empty?
    else
        true
    end
  end

end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文