我尝试查询对象的关联,并且仅返回其所有关联都具有特定值的对象。例如,如果用户具有成员资格关联,并且成员资格具有有效(布尔)字段,我想返回所有的集合仅具有有效身份的成员资格的用户:false 。
我现在正在使用的查询是:
User.includes(:memberships).where(memberships: {active: false})
但是,这会让我拥有非活动成员资格的所有用户,以及同时拥有有效:错误和有效:真实成员身份的所有用户。我尝试在这上面做一个额外的.where.not,但当然,它返回了同一组。
我考虑过映射用户集合并创建一个新数组,踢出具有活动成员资格的用户,但我需要将最终值保留为AR集合,因为我继续在控制器。
我更倾向于坚持使用ActiveRecord,但如果它不可行而我需要使用SQL,我也会对此持开放态度。
非常感谢任何帮助。谢谢!
答案 0 :(得分:0)
要排除同时具有有效和无效成员资格的用户,请尝试
User.includes(:memberships).where(memberships: {active: false}).where.not(memberships: {active: true})
此外 - 您可能希望使用#joins而不是#includes。如果您不需要访问除查询之外的成员资格,则无需将其加载到内存中(#include会这样做。)
这篇文章有一个很好的解释 - http://tomdallimore.com/blog/includes-vs-joins-in-rails-when-and-where/
答案 1 :(得分:0)
在这里结合一些事情 - 你想要一个LEFT OUTTER连接,所以确保正确构建你的SQL查询。检查
User.includes(:memberships).where(memberships: {active: false}).explain
或
User.includes(:memberships).where(memberships: {active: false}).to_sql
其次,试试:
User.joins(:memberships).where("memberships.active = ?", false)
或者尝试.merge
尝试,我喜欢使用:
User.joins(:memberships).merge(Membership.inactive)
假设您在.inactive
模型
Membership
def self.inactive
where(active: false)
end
只有当您需要将关系加载到内存中时才应该使用 .includes
。
排除拥有单个(多个)成员资格的任何用户的最简单方法是将其拆分为2个查询。
active_user_ids = Membership.active.pluck(:user_id).uniq
User.where("id NOT IN (?)", active_user_ids.join(","))