加入鑑於這兩款車型Rails的,最大的條件
class Article < AR::Base
belongs_to :tag
default_scope order('id DESC')
end
class Tag < AR::Base
has_many :articles
scope :featured, order(:ordering).limit(5)
end
我想要的方式來連接這兩個表這樣我可以檢索功能的標籤,併爲他們每個人的名單中的最新文章標籤有一個單一的查詢,像
Tag.featured.each do |tag|
p tag.name
p tag.articles.first.title # this will fetch the article in the tag with the highest id
end
這樣寫的這段代碼有(n+1) query problem,我試圖去優化它,因爲它會很頻繁地運行。我已經排除在featured
範圍的includes
調用,因爲它會加載前5個標籤的所有Article
(很多文章......)
在普通的舊SQL我可以加入使用類似的查詢這兩個表這
SELECT tag_id, MAX(id) FROM articles GROUP BY tag_id
# or in Rails
Article.select('MAX(id), tag_id').group(:tag_id)
+--------+---------+
| tag_id | MAX(id) |
+--------+---------+
| 14 | 26787 |
...
| 1 | 27854 |
| 5 | 27780 |
| 0 | 10953 |
+--------+---------+
作爲連接表我可以檢索所有的數據與一個單一的查詢。
如何在Rails和ActiveRecord中移植?
更新
我在AR方面需要執行的全查詢
SELECT a.*, t.*
FROM tags t
JOIN (SELECT MAX(id) AS latest, tag_id FROM articles GROUP BY tag_id) j ON j.tag_id = t.id
JOIN articles p ON j.latest = a.id
LIMIT 5
我試圖AR#find_by_sql
方法與最新的查詢,我得到正確的結果集,但後來我不能通過對象
sql = '...' # This holds the previous query
Tag.find_by_sql(sql).first.class
=> "Tag"
Tag.find_by_sql(sql).first.articles.first
=> nil # why???
更新2
也試圖與
Tag.joins('JOIN ... all my query join part here ...').first.articles.first
=> nil
但是我注意到,我可以直接使用我的文章字段作爲標籤字段,即我可以寫
Tag.find_by_sql(...).first.title # where title is a field of Article class
Tag.joins(...).first.title # where title is a field of Article class
但很明顯,我不能叫Article
實例方法。
因爲沒有其他答案,我會自己接受我自己的答案。 – Fabio