如何在Rails中搜索group_by与关联

时间:2018-06-06 09:22:42

标签: ruby-on-rails ruby

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

category.rb

class Category < ApplicationRecord
  has_many :job_categories, dependent: :destroy
  has_many :jobs, through: :job_categories
end

job.rb

class Job < ApplicationRecord
  has_many :job_categories, dependent: :destroy
  has_many :categories, through: :job_categories
end

job_category.rb

class JobCategory < ApplicationRecord
  belongs_to :category, counter_cache: :jobs_count
  belongs_to :job
end

schema.rb

create_table "categories", force: :cascade do |t|
  t.string "name"
  t.string "parent"
end

parent是一个维护组Technology以及此ruby,rails,programming等与技术相关的组的列。

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

Category.select(:id, :name, :parent).group_by{|p| p.parent}

并且它显示如下

技术

  • 红宝石

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

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

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

由于

2 个答案:

答案 0 :(得分:5)

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

jobs

这会将job_categories与相关键上的中间表jobswhere相关联,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" ) ) 子句将允许您选择要检索的内容

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" )) ,以下就足够了:

{{1}}

答案 1 :(得分:1)

使用关联has_many_through获取和分组记录的其他几个选项:

# Filtering by query
Job.joins(:categories).select('jobs.id, jobs.name, categories.parent').where('lower(categories.parent) LIKE lower(?)', "Technology").distinct.inspect
# => #<ActiveRecord::Relation [#<Job id: 1, name: "Developer">, #<Job id: 2, name: "Debugger">]>

# Grouping by categories.parent, return a hash
Job.joins(:categories).select('jobs.id, jobs.name, categories.parent').all.distinct.group_by(&:parent)
# => {"Technology"=>[#<Job id: 1, name: "Developer">, #<Job id: 2, name: "Debugger">], "Mechanics"=>[#<Job id: 3, name: "Technic">]}

# Accessing the hash by key
Job.joins(:categories).select('jobs.id, jobs.name, categories.parent').all.distinct.group_by(&:parent)["Technology"]
#=> [#<Job id: 1, name: "Developer">, #<Job id: 2, name: "Debugger">]