[英]Rails 5: How to order models by associated model attribute, and make them distinct
我在rails中有一個作用域,應該通過最后一個聊天消息created_at屬性來訂購一組對話。 就像這樣:
class Conversation < ApplicationRecord
has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do
def last_from_user
from_user.order("created_at ASC").last
end
def last_delivered_from_user
from_user.order("delivered_at ASC").last
end
def last_from_agent
from_agent.order("created_at ASC").last
end
end
default_scope { joins(:chat_messages).order("chat_messages.created_at desc").distinct }
end
例如,當一個ID為4的組織收到一條新消息時,我希望訂單為:
[4,1,2,3]
但是,我得到的是:
[1,2,3,4]
如果我刪除像這樣的獨特方法:
class Conversation < ApplicationRecord
default_scope { joins(:chat_messages).order("chat_messages.created_at desc") }
end
會話被安排得很好,但是重復了:[4,1,2,3,4]
我的chat_message模型如下:
class ChatMessage < ApplicationRecord
# Associations
# ------------------------------------------------------------
belongs_to :conversation
end
我無法使用“唯一”方法,因為這將使分頁無法正常工作。
但是,當對話中包含多個消息時,“區別”方法會弄亂順序。 此作用域按創建的順序(而不是我實際需要的順序)返回對話。
如果我們刪除Rails並只看一下SQL,它就會更加清晰。 您所遇到的是一個經典的SQL問題,即試圖獲取基於聯接的最大或最小排序的列表。
您正在運行這樣的查詢:
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
您將在每一對對話和chat_messages中返回一行 。 這就是為什么重復的原因。
您不能對此使用不distinct
。
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
ERROR 3065 (HY000): Expression #1 of ORDER BY clause is not in SELECT list,
references column 'test.chat_messages.created_at' which is not in SELECT list;
this is incompatible with DISTINCT
如果您使用select distinct conversations.*, chat_messages.created_at
您將回到開始的地方。
我不確定.distinct
在做什么,但是它可能會引發異常。
相反,請刪除帶有group by conversation.id
的重復項。 現在您有了分組查詢,可以order by max(chat_messages.created_at) desc
。
select c.*
from conversations c
join chat_messages cm
on cm.conversation_id = c.id
group by c.id
order by max(cm.created_at) desc
將其轉換為Rails ...
Conversations
.joins(:chat_messages)
.group(:id)
.order("max(chat_messages.created_at) desc")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.