如何在Rails中搜索group_by与关联

jes*_*ica 3 ruby ruby-on-rails

我不知道我是如何描述这个问题的,起初我想展示我的模型,它维持下面的关系

category.rb

class Category < ApplicationRecord
  has_many :job_categories, dependent: :destroy
  has_many :jobs, through: :job_categories
end
Run Code Online (Sandbox Code Playgroud)

job.rb

class Job < ApplicationRecord
  has_many :job_categories, dependent: :destroy
  has_many :categories, through: :job_categories
end
Run Code Online (Sandbox Code Playgroud)

job_category.rb

class JobCategory < ApplicationRecord
  belongs_to :category, counter_cache: :jobs_count
  belongs_to :job
end
Run Code Online (Sandbox Code Playgroud)

schema.rb

create_table "categories", force: :cascade do |t|
  t.string "name"
  t.string "parent"
end
Run Code Online (Sandbox Code Playgroud)

parent是一个维护集团的列,Technology与此类似的ruby,rails,programming技术相关.

以下是我按类别显示的查询

Category.select(:id, :name, :parent).group_by{|p| p.parent}
Run Code Online (Sandbox Code Playgroud)

它就像这样显示出来

技术

  • 红宝石
  • 轨道
  • 等等

现在我想通过技术显示组中的所有作业,我对此有一个查询

Job.joins(:categories).where('lower(categories.parent) LIKE lower(?)', "%#{params[:parent]}%")
Run Code Online (Sandbox Code Playgroud)

并且它显示错误的输出,就像我只有一个类别,ruby,rails然后这一个作业显示两次,一个用于ruby,一个用于rails.

谢谢

kid*_*ils 5

您的关联是正确的,您可以通过以下方式检索某些类别的所有唯一作业:

Job.joins(:job_categories).joins(:categories).where('lower(categories.parent) LIKE lower(?)', "%#{params[:parent]}%").distinct
Run Code Online (Sandbox Code Playgroud)

这将jobs与中间表job_categoriesjobs相关的键和where子句连接,然后允许您选择要检索的内容.

SELECT DISTINCT "jobs" .*
FROM "jobs" INNER
JOIN "job_categories" ON "job_categories" ."job_id" = "jobs" ."id" INNER
JOIN "job_categories" "job_categories_jobs_join" ON "job_categories_jobs_join" ."job_id" = "jobs" ."id" INNER
JOIN "categories" ON "categories" ."id" = "job_categories_jobs_join" ."category_id"
WHERE
(
 lower ( categories.parent ) LIKE lower ( "Technology" ) )
Run Code Online (Sandbox Code Playgroud)

更新:实际上,我们不需要显式连接job_categories,以下内容就足够了:

Job.joins(:categories).where('lower(categories.parent) LIKE lower(?)', "%#{params[:parent]}%").distinct

SELECT DISTINCT "jobs".* FROM "jobs" INNER JOIN "job_categories" ON "job_categories"."job_id" = "jobs"."id" INNER JOIN "categories" ON "categories"."id" = "job_categories"."category_id" WHERE (lower ( categories.parent ) LIKE lower ( "Technology" ))
Run Code Online (Sandbox Code Playgroud)