以更高效的方式从 PostgreSQL 数据库中检索数据

Retrieving data from PostgreSQL DB in a more efficient way

我正在使用 PostgreSQL 开发实时聊天应用程序,但遇到以下问题:

当用户登录时,我需要获取所有不是登录用户的用户,以便将它们显示在应用程序的侧边栏上。

每个用户下方应显示已登录用户或其他用户发送的最新消息。

我正在尝试执行高效查询,以便立即检索所有用户及其最新消息,但没有成功。

这是我的表格:

我最初尝试做类似的事情:

SELECT users.id, users.first_name, users.last_name, users.image, messages.sender_id, messages.recipient_id, messages.content
FROM users LEFT JOIN messages on users.id = messages.sender_id OR users.id = messages.recipient_id
WHERE (messages.sender_id = 1 OR messages.recipient_id = 1) AND users.id != 1
GROUP BY users.id
ORDER BY messages.created_at DESC;

我得到了这个错误:

我的临时解决方案是从数据库中获取所有用户,在服务器上映射它们并执行另一个查询,该查询使用 - ORDER BY created_at DESC LIMIT 1 发回用户之间的最新消息。

我相信还有更有效的方法,如果有任何帮助,我将不胜感激!

如果我没听错,你可以使用条件逻辑 select 在 logged-in 用户和任何其他用户之间交换(发送或接收)的消息,然后加入对应的用户记录。要获得每个用户的最新消息,distinct on 在 Postgres 中很方便。

考虑:

select distinct on (u.id) u.id, ... -- enumerate the columns you want here
from (
    select m.*, 
        case when sender_id = 1 then recipient_id else sender_id end as other_user_id
    from messages m
    where 1 in (m.sender_id, m.recipient_id)
) m
inner join users u on u.id = m.other_user_id
order by u.id, m.created_at desc

我们也可以用横向连接来表达:

select distinct on (u.id) u.id, ... 
from messages m
cross join lateral (values 
    (case when sender_id = 1 then recipient_id else sender_id end as other_user_id)
) as x(other_user_id)
inner join users u on u.id = x.other_user_id
where 1 in (m.sender_id, m.recipient_id)
order by u.id, m.created_at desc