2015-09-03 76 views
0

說我有這個簡化的模型設置如何查找沒有關聯的數據庫記錄?

用戶:

has_many :logs 

登錄:

attr_accessible :key, :value 
belongs_to :user 

當用戶接觸,應用程序創建了

Log.create(user: user, key: "contacted", value: "by admin") 
日誌此事件

有許多其他類型的日誌,由t繼承人key屬性值。

我想寫一個範圍,將返回所有從未聯繫過的用戶。
到目前爲止,我有

scope :never_contacted, -> { joins(:logs).where.not("logs.key = ?", "contacted").uniq } 

不幸的是,這似乎只返回比「接觸」等日誌,並留下了具有完全沒有日誌的用戶。

我想有可能以「反」積極的查詢,例如

scope :contacted, -> { joins(:logs).where("logs.key = ?", "contacted").uniq } 
scope :never_contacted, -> { (all - contacted) } 

但我也懷疑這樣的做法是非常低效的。

是否有可能查詢沒有與「contacts」關聯的日誌作爲關鍵屬性的用戶?

回答

2

可以通過單個SQL查詢來實現更正結果,但您需要一點良好的舊SQL。

User.joins("LEFT JOIN logs ON logs.user_id = users.id").where("logs.id IS NULL") 

上述代碼強制LEFT JOIN(如由缺省AR創建INNER JOIN)和獲取所有在沒有相應日誌中的logs表中的用戶。

你可以打包爲一個範圍

scope :never_contacted, -> { joins("LEFT JOIN logs ON logs.user_id = users.id").where("logs.id IS NULL") } 
+0

此查詢不會只返回沒有日誌的用戶嗎?那些除了「聯繫」之外還有其他日誌的用戶呢? – Epigene

+1

只需在WHERE中添加一個額外的OR條件。 –

0

我查詢SQL直接與OR條件,如果它是關於效率。

scope :never_contacted, -> { joins(:logs).where("logs.key IS NULL OR logs.key <> ?", "contacted").uniq } 
+0

謝謝,這看起來很完美。我仍然覺得奇怪,「無日誌」和「只有其他日誌」的情況必須分開處理。猜猜SQL不是專爲負面查找而設計的。 – Epigene

+0

這也不會削減它。 「logs.key IS NULL」僅返回具有沒有密鑰的日誌的用戶,而不是沒有日誌的用戶。如果只是有一種方法可以將這個答案與Simone Carletti的答案結合起來。 – Epigene

相關問題