【问题标题】:How would I go about searching for Users querying multiple associations?我将如何搜索查询多个关联的用户?
【发布时间】:2016-06-29 03:03:05
【问题描述】:

好的。假设有一个包含多个连接表的用户模型。

用户

has_many :languages
has_many :skills
has_many :languages, through: :user_langauges
has_many :skills, through: :user_skills

如果我用类似的参数命中一个端点

"user"=>
  { "email"=>"test@123.com",
   "languages"=>"["French", Spanish]",
   "skills"=>"["accounting", "leadership"]"
}

如何搜索符合上述条件的用户?我主要关心的是如何搜索与“语言”和“技能”相关的用户。是不是最好把所有用户都拿下来,比较哪些用户是一样的?比如:

french = French.users
leadership = Leadership.users
french & leadership # => "users that exist in both?"

显然,有更多的逻辑,但我觉得一般的想法是征税和低效的。但我确信 Rails 已经想到了一种更优雅的方式,这就是为什么我需要 Rails 大师的指导:)

编辑:如果重要的话,我有一个 Psql 数据库。

【问题讨论】:

  • 如果你这样做可能会奏效:User.joins(user_skills: :skills, user_languages: :languages).where("conditions")。如果您想使用上述解决方案,您可以这样做:french.where("leadership condition")
  • @Deep 你不需要将中间表添加到连接中,这是由 has_many 处理的。

标签: ruby-on-rails ruby postgresql ruby-on-rails-4 search


【解决方案1】:

不,您不想比较 Ruby 中的用户。如果您有很多用户/技能/语言,它会加载大量数据并且性能不佳。

这就是数据库的用途。查看 AR 指南以了解如何查询数据库:http://guides.rubyonrails.org/active_record_querying.html 我还建议您阅读 SQL,因为 AR 只能帮助您构建 SQL 查询。但力量来自你的数据库。

这是一个大概的工作示例:

User.joins(:languages, :skills).where(skills: {name: ['Ruby', 'Marketing']}, languages: {name: 'French'}).uniq

假设:用户、技能和语言有一个属性 name 为您的架构进行调整。

这将搜索具备以下条件的用户:(技能 Ruby 或营销)并会说法语。

如果您不想拥有:ruby AND marketing AND french,那么查询会变得更复杂。

更新: 如前所述,AND 组合更复杂。您将需要使用 GROUP BY 和 HAVING,或者可以提供子查询来尝试计算技能。这是可以工作的原始 SQL 查询:

SELECT users.* FROM (
SELECT users.* FROM "users"
INNER JOIN "user_skills" ON "user_skills"."user_id" = "users"."id"
INNER JOIN "skills" ON "skills"."id" = "user_skills"."skill_id"
WHERE skills.name IN ('Ruby', 'Marketing')
GROUP BY users.id
HAVING COUNT(*) = 2
) users
INNER JOIN "user_languages" ON "user_languages"."user_id" = "users"."id"
INNER JOIN "languages" ON "languages"."id" = "user_languages"."language_id"
WHERE languages.name IN ('German', 'French', 'English')
GROUP BY users.id, users.name, users.created_at, users.updated_at
HAVING COUNT(users.*) = 3

数字 (2, 3) 必须是您需要的匹配数(2 种技能,3 种语言)。

【讨论】:

  • 好的,这对包括资源在内有很大帮助。做“Ruby”和“Marketing”和“FRNCH”是我的目标。希望我能从您提供的文档中得到答案。我正在尝试使用搜索引擎构建一个工具来缩小员工技能,用户可以根据查询“过滤”员工。
  • 我设法让查询适用于 Rails。但现在我只是想知道有这么长的查询有多“好”,查询连接是否自然?我正在使用的模型非常庞大,因为我正在为客户找到他们的员工提供一种方式。如果我想添加另一个联接怎么办。有没有更好的方法来解决这个问题?或者只是效仿并在该行添加更多查询?
  • "Worker.select('workers.*').joins(:months).group('workers.id').where(search_params).having('count(months.id) > = ' + havingMonths ).uniq"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多