首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我想在Rails中查找没有关联记录的记录

我想在Rails中查找没有关联记录的记录
EN

Stack Overflow用户
提问于 2011-03-16 07:47:10
回答 8查看 80.2K关注 0票数 205

考虑一个简单的关联..。

代码语言:javascript
复制
class Person
   has_many :friends
end

class Friend
   belongs_to :person
end

要让所有在ARel和/或meta_where上没有朋友的人都加入进来,最干净的方法是什么?

那么has_many :直通版本呢?

代码语言:javascript
复制
class Person
   has_many :contacts
   has_many :friends, :through => :contacts, :uniq => true
end

class Friend
   has_many :contacts
   has_many :people, :through => :contacts, :uniq => true
end

class Contact
   belongs_to :friend
   belongs_to :person
end

我真的不想使用counter_cache --从我读到的内容来看,它不适用于has_many:

我不想提取所有的person.friends记录,然后在Ruby语言中遍历它们--我希望有一个可以在meta_search gem中使用的查询/范围

我不关心查询的性能成本

离实际的SQL越远越好。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2011-03-16 08:33:30

这仍然非常接近SQL,但在第一种情况下,它应该会让没有朋友的每个人:

代码语言:javascript
复制
Person.where('id NOT IN (SELECT DISTINCT(person_id) FROM friends)')
票数 124
EN

Stack Overflow用户

发布于 2011-04-07 01:05:11

更新4- Rails 6.1

感谢Tim Park指出,在即将到来的6.1中,您可以这样做:

代码语言:javascript
复制
Person.where.missing(:contacts)

多亏了他链接到的the post

更新3- Rails 5

感谢@Anson出色的Rails 5解决方案(下面给他一些+1的答案),你可以使用left_outer_joins来避免加载关联:

代码语言:javascript
复制
Person.left_outer_joins(:contacts).where(contacts: { id: nil })

我在这里包含了它,这样人们就会找到它,但他应该为此得到+1。很棒的新增功能!

更新2

有人问到了相反的问题,没有人的朋友。正如我在下面评论的那样,这实际上让我意识到最后一个字段(上面::person_id)实际上不必与您返回的模型相关,它只需要是连接表中的一个字段。它们都将是nil,所以可以是其中的任何一个。这为上述问题提供了更简单的解决方案:

代码语言:javascript
复制
Person.includes(:contacts).where(contacts: { id: nil })

然后切换到返回没有人的朋友变得更加简单,您只需更改前面的类:

代码语言:javascript
复制
Friend.includes(:contacts).where(contacts: { id: nil })

更新

在评论中有一个关于has_one的问题,所以只需要更新。这里的诀窍是,includes()需要关联的名称,而where需要的是表的名称。对于has_one,关联通常以单数形式表示,因此会发生变化,但where()部分保持不变。因此,如果仅使用Person has_one :contact,则语句将为:

代码语言:javascript
复制
Person.includes(:contact).where(contacts: { person_id: nil })

原创

更好的:

代码语言:javascript
复制
Person.includes(:friends).where(friends: { person_id: nil })

对于hmt来说,这基本上是一样的,你依赖于一个没有朋友的人也将没有联系人的事实:

代码语言:javascript
复制
Person.includes(:contacts).where(contacts: { person_id: nil })
票数 516
EN

Stack Overflow用户

发布于 2013-09-30 00:05:09

没有朋友的人

代码语言:javascript
复制
Person.includes(:friends).where("friends.person_id IS NULL")

或者至少有一个朋友

代码语言:javascript
复制
Person.includes(:friends).where("friends.person_id IS NOT NULL")

您可以通过在Friend上设置作用域来使用Arel完成此操作

代码语言:javascript
复制
class Friend
  belongs_to :person

  scope :to_somebody, ->{ where arel_table[:person_id].not_eq(nil) }
  scope :to_nobody,   ->{ where arel_table[:person_id].eq(nil) }
end

然后,至少有一个朋友的人:

代码语言:javascript
复制
Person.includes(:friends).merge(Friend.to_somebody)

没有朋友的人:

代码语言:javascript
复制
Person.includes(:friends).merge(Friend.to_nobody)
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5319400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档