【发布时间】:2021-03-06 19:35:27
【问题描述】:
如果我们有 3 个模式:ChatRoom、User 和 Message
ChatRoom.ex
schema "chat_rooms" do
has_many(:users, User)
has_many(:messages, through: [:users, :messages])
end
Ecto 是否有既定的方式来“获取一个聊天室,以及关联用户的所有消息都按消息上的某个字段排序”?
我最初只是想简单地获得一个聊天室和preload 它,它的所有消息都按message.inserted_at 排序,并且可以在两个查询中执行此操作(并了解如何在单个查询中执行此操作结合 join 和 preload),但是当需要按 has_many :through 资源上的值排序时,它似乎将相同的排序应用于中间关联(在本例中为用户)。
示例问题:因此,如果聊天室 A 中有两个用户(user1 首先加入,user2 第二加入),我们的消息序列为:
- user1:“嗨”
- user2:“你好”
- user1:“再见”
- user2:“再见”
如果我这样做了:
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 结果实际上会像这样列出:
- user1 的“嗨”
- user1 的“再见”
- user2 的“你好”
- user2 的“告别”
这显然不是目标。如何在 Ecto 中对预加载的查询进行排序而不将其应用于连接资源?
【问题讨论】:
-
我可以通过加入 chat_rooms 与用户和消息,然后通过 messages.inserted_at 订购并选择我想要的(来自 chat_rooms 和所有消息等的几个属性)来解决这个问题,但我主要是想知道预加载绑定魔法等是否有更“Ecto-y”的方式
-
我确认 Ecto 正在将排序预加载查询应用于消息表上的 user_id 以及所需的 insert_at,这绝对是导致这种不良行为的原因,想知道 Jose 或其他人是否可以解释原因
SELECT m0."id", m0."content", m0."user_id", m0."inserted_at", m0."updated_at", m0."user_id" FROM "messages" AS m0 WHERE (m0."user_id" = ANY($1)) ORDER BY m0."user_id", m0."inserted_at" [[<<...>>, <<...>>]]
标签: elixir phoenix-framework ecto