ruby-on-rails – 在has_many关联中选择所有包含某些条件的记录 – Ruby On Rails

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 在has_many关联中选择所有包含某些条件的记录 – Ruby On Rails前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个模型profile.rb与以下关联
class User < ActiveRecord::Base
   has_one :profile
end

class Profile < ActiveRecord::Base
    has_many :skills
    belongs_to :user
end

我有一个模型skill.rb与以下关联

class Skill < ActiveRecord::Base
    belongs_to :profile
end

我在技能表中有以下条目

id:         name:           profile_id:
====================================================
1           accounting          1
2           martial arts        2
3           law                 1
4           accounting          2
5           journalist          3
6           administration      1

等等,我怎么能查询所有的配置文件,比方说,“会计”&考虑到上述重新编码,“管理”技能将是id为1的概要.到目前为止,我试过以下

Profile.includes(:skills).where(skills: {name: ["accounting","administration"]} )

但不是找到id为1的个人资料 – 它让我[1,2],因为id为2的个人资料拥有“会计”技能,并且在数据库中执行“IN”操作

注意:我正在使用postgresql并且问题不仅仅是描述的配置文件的特定ID(我仅用作示例) – 原始问题是获取包含这两个提到的技能的所有配置文件.

我的activerecord join在postgres中触发以下查询

SELECT FROM "profiles" LEFT OUTER JOIN "skills" ON "skills"."profile_id" = "profiles"."id" WHERE "skills"."name" IN ('Accounting','Administration')

Vijay Agrawal以下的答案是我已经在我的应用程序中已经有的东西,他和我的,查询使用IN通配符导致包含任何技能的配置文件ID,而我的问题是获得包含两种技能的配置文件ID.我确信必须有一种方法以原始问题中列出的相同查询方式修复此事,我很想知道这种方式.我希望我能得到更多帮助 – 谢谢

为清楚起见,我想在模型中查询具有多种技能的所有配置文件,并且与配置文件模型具有has_many关系 – 使用配置文件作为主要表而不是技能

使用Profile作为主表的原因是在分页中我不想从相关表中获取所有技能,比如20_000或更多行,然后根据profile.state列进行过滤.相反,任何人都希望只选择符合profile.state,profile.user.is_active和其他列的5条记录条件并匹配技能,而无需检索数千条不相关的记录,然后再次过滤它们.

解决方法

您应该这样做以获得具有会计和管理技能的所有profile_ids:
Skill.where(name: ["accounting","administration"]).group(:profile_id).having("count('id') = 2").pluck(:profile_id)

如果您需要配置文件详细信息,可以将此查询放在Profile for id的where子句中.

注意查询中的数字2,它是在where子句中使用的数组的长度.在这种情况下[“会计”,“管理”].长度

更新::

基于更新的问题描述,您可以使用select和add子查询来确保它在一个查询中发生,而不是使用pluck.

Profile.where(id: Skill.where(name: ["accounting","administration"]).group(:profile_id).having("count('id') = 2").select(:profile_id))

更多的是你可以控制排序,分页和其他where子句.不要在编辑中提到有任何问题.

更新2 ::

另一种使配置文件与两种技能相交的方法(可能效率低于上述解决方案):

profiles = Profile

["accounting","administration"].each do |name|
  profiles = profiles.where(id: Skill.where(name: name).select(:profile_id))
end

猜你在找的Ruby相关文章