预加载和排序 has_many 时的不良行为:通过关联

Undesired behavior when preloading and ordering a has_many :through association

如果我们有 3 个模式:聊天室、用户和消息

ChatRoom.ex
schema "chat_rooms" do
  has_many(:users, User)
  has_many(:messages, through: [:users, :messages])
end

Ecto 是否有一个既定的方法来“获取聊天室,并且关联用户的所有消息都按消息上的某个字段排序”?

我最初只是想简单地获得一个聊天室,preload 它的所有消息都按 message.inserted_at 排序,并且可以在两个查询中做到这一点(并了解如何在结合 joinpreload) 的单个查询中执行此操作,但是当需要按 has_many 上的值排序时:through 资源,它似乎将相同的排序应用于中间关联(在此示例中为用户)。

示例问题:因此,如果聊天室 A 中有两个用户(用户 1 第一个加入,用户 2 第二个加入),并且我们的消息序列为:

如果我这样做了:

sorted_message_query = from(message in Message, order_by: message.inserted_at)

from(chat_room in ChatRoom,
  where: chat_room.id == ^chat_room_id,
  preload: [messages: ^sorted_message_query]
)

chat_room 上的 messages 结果实际上会像这样列出:

  1. 用户 1 的“嗨”
  2. user1 的“再见”
  3. user2 的“你好”
  4. 用户2的“告别”

这显然不是目标。您如何在 Ecto 中对预加载的查询进行排序而不将其应用于连接资源?

好吧,我不确定为什么我会发现这一天如此令人困惑,脑子放屁。显式加入这两个关联然后预加载那些现有的连接对我来说是这样的:

  from chat_room in ChatRoom,
    where: chat_room.id == ^chat_room_id,
    join: user in assoc(chat_room, :users),
    left_join: message in assoc(user, :messages),
    preload: [users: user, messages: message],
    order_by: message.inserted_at