想要在Rails中查找没有相关记录的记录考虑一个简单的关联......class Person
has_many :friendsendclass Friend
belongs_to :personend让所有在ARel和/或meta_where中没有朋友的人最简洁的方法是什么?然后是一个has_many:通过版本class Person
has_many :contacts
has_many :friends, :through => :contacts, :uniq => trueendclass Friend
has_many :contacts
has_many :people, :through => :contacts, :uniq => trueendclass Contact
belongs_to :friend
belongs_to :personend我真的不想使用counter_cache - 而且我从我读过的内容中看起来并不适用于has_many:通过我不想拉出所有的person.friends记录并在Ruby中循环它们 - 我希望有一个可以与meta_search gem一起使用的查询/范围我不介意查询的性能成本而离实际SQL越远越好......
3 回答
Qyouu
TA贡献1786条经验 获得超11个赞
这仍然非常接近SQL,但它应该让所有人在第一种情况下没有朋友:
Person.where('id NOT IN (SELECT DISTINCT(person_id) FROM friends)')
胡子哥哥
TA贡献1825条经验 获得超6个赞
更好:
Person.includes(:friends).where( :friends => { :person_id => nil } )
对于hmt它基本上是一样的,你依赖的事实是没有朋友的人也没有联系人:
Person.includes(:contacts).where( :contacts => { :person_id => nil } )
更新
has_one
在评论中有一个问题,所以只是更新。这里的技巧是includes()
期望关联的名称,但where
期望表的名称。对于一个has_one
关联通常会以单数表示,以便更改,但该where()
部分保持不变。所以如果Person
只有has_one :contact
你的陈述是:
Person.includes(:contact).where( :contacts => { :person_id => nil } )
更新2
有人询问反向,没有人的朋友。正如我在下面评论的那样,这实际上让我意识到最后一个字段(上面的:person_id
:)实际上并不需要与你返回的模型相关,它只需要是连接表中的一个字段。他们都将是nil
如此,它可以是任何一个。这导致了上述更简单的解决方案:
Person.includes(:contacts).where( :contacts => { :id => nil } )
然后切换这个以返回没有人的朋友变得更简单,你只改变前面的班级:
Friend.includes(:contacts).where( :contacts => { :id => nil } )
更新3 - Rails 5
感谢@Anson提供优秀的Rails 5解决方案(下面给出他的答案为+ 1),您可以使用left_outer_joins
以避免加载关联:
Person.left_outer_joins(:contacts).where( contacts: { id: nil } )
我把它包括在这里,所以人们会找到它,但他应该得到+ 1s。太棒了!
- 3 回答
- 0 关注
- 668 浏览
添加回答
举报
0/150
提交
取消