使用排序选择组中的最新记录
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
模型,从而使用QuerySet
的User
对象:
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 theUser
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(..)
确实不见了。已更新。以上是关于使用排序选择组中的最新记录的主要内容,如果未能解决你的问题,请参考以下文章