【问题标题】:Find all record without association with a certain field查找与某个字段没有关联的所有记录
【发布时间】:2016-08-30 11:23:24
【问题描述】:
我的问题和这个问题很相似:Want to find records with no associated records in Rails 3
但有一个转折点。让我们使用他们的示例并添加我的问题:
class Person
has_many :friends
end
class Friend
belongs_to :person
attr_accessor :type # this can be 'best' or 'acquaintance'
end
我想让所有人都没有“最好的”朋友。我看到的大多数情况下的正常查询是让没有任何朋友的人。那将是:
Person.includes(:friends).where( :friends => { :person_id => nil } )
但这不是我想要的。有没有办法让所有没有“最好”朋友的人不管他们有多少其他类型的朋友?
【问题讨论】:
标签:
ruby-on-rails
ruby
ruby-on-rails-3
activerecord
rails-activerecord
【解决方案1】:
如果您使用的是支持否定查询的 rails 4.2,您可以执行以下操作:
Person.includes(:friends).where.not( friends: { type: "best" } )
在任何其他情况下:
Person.includes(:friends).where("friends.type != 'best'")
更新
可能有点离题,但您可以考虑使用活动记录中的enum,以便映射此类内容,例如:
class Friend
belongs_to :person
enum type: {best: 0, acquaintance: 1}
end
那么你可以这样查询:
Person.includes(:friends).where.not( friends: { type: Friend.types[:best] } )
这使得它更具可读性、对 ruby 友好并且避免使用字符串,因为该值以整数形式存储在数据库中。
【解决方案2】:
最直接的方法是使用NOT EXISTS 子查询:
Person.where('NOT EXISTS(SELECT 1 FROM friends WHERE person_id=persons.id AND type=?)', 'best')
您可以将其定义为Person 上的范围,以便于组合。
注意:我还想指出,虽然 Gustavo 的解决方案看起来像您期望的那样,但它会返回任何有朋友但不是他们最好朋友的人(不仅仅是没有任何最好朋友的人)。这是由于 SQL 的 where 子句如何在每行基础上运行,并且难以断言组或一对多关系。