使用排序选择组中的最新记录

Posted

技术标签:

【中文标题】使用排序选择组中的最新记录【英文标题】:Select latest record in the group with ordering 【发布时间】:2022-01-10 00:13:32 【问题描述】:

我在使用 Django ORM 编写查询时遇到问题,我想查找每个组中的最新记录。我将聊天消息放入模型中,我想找到每个用户的最新聊天,并显示每个用户的最新聊天,并在主屏幕上显示最新用户的聊天,就像在 WhatsApp、Skype 或类似应用程序中一样。目前,我正在使用以下查询,

Chats.objects.all().order_by('user_id', '-date').distinct('user_id')

使用它,我可以获取每个用户的最新聊天记录,但我无法获取正确的顺序。查询的结果是按照用户在数据库中创建的顺序,我理解是正确的,但我想在顶部显示发送最新聊天的用户。

我的Models.py

class Chats(models.Model):
    user_id = models.ForeignKey(User, on_delete=models.CASCADE)
    chat = models.CharField(max_length=1023, null=True, blank=True)
    date = models.DateTimeField(auto_now_add=True)

非常感谢,如果需要任何其他信息,请告诉我。

【问题讨论】:

【参考方案1】:

选项 1:在 Django/Python 层排序

项目首先按user_id排序,只有在平局的情况下,才会采用日期最晚的项目。但这意味着您最终会为每个用户获得一个Chats 对象,user_id 排序

我认为您唯一的选择是在 Django/Python 级别对其进行排序,因此将其包装到一个列表中,然后按 date 排序:

from operator import attrgetter

items = list(Chats.objects.order_by('user_id', '-date').distinct('user_id'))
items.sort(key=attrgetter('date'), reverse=True)
# work with items

然后在模板中渲染items


选项 2:改为注释 User 模型

另一种选择是注释User 模型,从而使用QuerySetUser 对象:

from django.db.models import Max, OuterRef, Subquery

User.objects.filter(
    chats__isnull=False
).annotate(
    last_date=Max('chats__date'),
    last_message=Subquery(
        Chat.objects.filter(user_id=OuterRef('pk')).order_by('-date').value('chat')[:1]
    )
).order_by('-last_date')

这里的User 对象将有一个额外的属性.last_date 带有对象的最新日期时间,.last_message 带有该消息。


注意:通常使用settings.AUTH_USER_MODEL [Django-doc] 引用用户模型比直接使用User model [Django-doc] 更好。更多信息可以查看referencing the User model section of the documentation。

【讨论】:

如果他想要发送最新聊天的用户,他不应该只是翻转订单的优先级吗?还是完全删除 user_id? @WillemVanOnsem 非常感谢您的回复,这会不会很慢?随着用户数量会以非常快的速度增长?我这里也实现了分页。 @KeoniGarner:那行不通。 PostgreSQL 中 .distinct('user_id') 的整个想法是首先对要检索最新项目的项目进行排序:docs.djangoproject.com/en/dev/ref/models/querysets/#distinct 这是一个 PostgreSQL 独有的功能。 @Dexter:唯一的其他选择是注释 User 对象,因此不依赖此 PostgreSql-only 功能,因为它基本上“滥用”排序以获取每组的最新项目. @Dexter:.values(..) 确实不见了。已更新。

以上是关于使用排序选择组中的最新记录的主要内容,如果未能解决你的问题,请参考以下文章

选择组中的最新值

从每组中的 3 个表中选择 sql 中具有最新日期的行

mysql选择组中的最新时间戳

选择每组中的最后一条记录

如何根据日期选择组中的单行?

从每个组中获取最新记录