class Post
has_one :latest_comment, -> { order(created_at: :desc) }, class_name: 'Comment'
end
我想做類似的事情:
Post.joins(:latest_comment).pluck('latest_comment.id')
但它不是有效的語法,它不起作用。
Post.joins(:latest_comment).pluck('comments.id')
上面的作品,但它回傳一個帖子的所有評論的ID,而不僅僅是最新的。
uj5u.com熱心網友回復:
ActiveRecord::Association 是圍繞 SQL 連接的一個非常泄漏的抽象,因此has_one :latest_comment除非您在 Post 的實體上呼叫它,否則您的關聯實際上不會在連接表中為每條記錄回傳一行。
相反,當您運行時,Post.joins(:latest_comment).pluck('comments.id')您會得到:
SELECT "comments"."id"
FROM "posts"
INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
ActiveRecord 實際上不夠聰明,無法知道您想從評論表中獲取唯一值 - 它實際上只是表現得像一個has_many關聯。在它的辯護中,這實際上不是以多語種方式做的事情。
相反,您想要做的是從評論表中選擇行并獲得不同的值:
Comment.order(:post_id, created_at: :desc)
.pluck(Arel.sql('DISTINCT ON (post_id) id'))
DISTINCT ON是 Postgres 特定的。這里的確切方法將在 RDBMS:es 之間有所不同,并且還有許多其他選擇,例如橫向連接、視窗函式等,具體取決于您的性能要求。
uj5u.com熱心網友回復:
我找不到一個好的現有答案。這是最接近的。
問題不是真的pluck。問題是加入 ahas_one與加入表本身相同。在這種情況下,它相當于Post.joins(:comments).
在不使用自定義 SQL 或Arel的情況下,一個簡單的解決方案是直接加載記錄:
Post.includes(:latest_comment) # eager-loads latest_comments in subquery
.find_each # optional: batches data to save memory
.filter_map(&:latest_comment) # map to `latest_comment` and remove nils
.map(&:id) # finally, get the ids
這并不像 a 那樣高效,pluck因為它檢索兩個表上的每一列并實體化所有模型實體。
select(:id)您可以通過添加after來稍微提高性能,Post以便它只檢索idfor 帖子。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/464557.html
標籤:轨道上的红宝石
上一篇:RollifyGemUserhas_manypolls/roles和Poll有很多回答者,只有一個管理員
下一篇:如何將函式指標傳遞給c中的函式?
