2017-02-03 95 views
0

我有一個簡單的問題RoR關於多對多關係(has_many through:)。所以我有一個Tweet模型,它有很多Tag,反之亦然。查詢過濾與Rails has_many通過

您有索引操作和視圖,您可以在其中顯示帶有標籤的所有推文,但您也可以通過標籤進行篩選。還有一點細節,Tweet可以沒有標籤。

所以,如果我做這樣的事情:

Tweet.includes(:tags).where(tags: { name: #2017 })

如果然後過濾,你只會得到的標籤,你過濾,但不是所有的標籤,有是爲Tweet。 F.E.如果Tweet的標籤爲#2017, #2016, #2015,那麼最終您在視圖中只能獲得#2017

所以你可以做這樣的事情解決這個問題:

Tweet.joins(:tags).where(tags: { name: #2017 })

然後你會得到所有標籤爲每個鳴叫。

但問題是,如果索引頁面沒有過濾器,我想要所有的推文顯示,沒有標籤的事件。

當然,你可以做一個黑客入侵,如檢查標記參數是否存在Tweet.joins else Tweet.includes

有沒有辦法在1個查詢中做到這一點,並沒有黑客?此外,這背後的機制是什麼。我瞭解includes or LEFT OUTER JOIN背後的邏輯,因爲它只是在您的中間表中映射tweet_id和'tag_id',然後將此id轉換爲Tag表,當您有類似where的查詢時,會提到上面的內容。但是,爲什麼INNER JOIN讓我給所有標籤,給我的問題。

感謝您的回答。

回答

1

其因includes做的預先加載,當您查詢

Tweet.includes(:tags).where(tags: {name: "2017"}) 

它渴望加載所有的標籤名稱鳴叫爲2017 Tweet.tags不會再次運行該數據庫查詢,將有標籤只有一個值。

但在案件的加入

Tweet.joins(:tags).where(tags: {name: "2017"}) 

它的腸子加入,只找到其中​​有標籤和標籤名稱是2017年當你做Tweet.tags找到鳴叫後的鳴叫,它運行的數據庫查詢再次找到所有相關的標籤,它們會給你想要的結果。