想要在Rails中查找没有相关记录的记录

想要在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越远越好......


繁花如伊
浏览 627回答 3
3回答

Qyouu

这仍然非常接近SQL,但它应该让所有人在第一种情况下没有朋友:Person.where('id NOT IN (SELECT DISTINCT(person_id) FROM friends)')

胡子哥哥

更好: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。太棒了!

凤凰求蛊

smathy有一个很好的Rails 3答案。对于Rails 5,您可以使用left_outer_joins以避免加载关联。Person.left_outer_joins(:contacts).where( contacts: { id: nil } )查看api文档。它是在拉取请求#12071中引入的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Ruby