【问题标题】: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)

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

【问题讨论】:

    标签: django django-models django-rest-framework django-orm


    【解决方案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(..) 确实不见了。已更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多