想要在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 關注
- 717 瀏覽
添加回答
舉報
0/150
提交
取消