查询Django中所有类型的每个唯一类型的第n个最新条目



我研究过这个问题,答案是关于获得每种类型的最新信息,例如这个主题。

不同的是,对于ALL类型,我想获得每个类型的n最新项目。在我得到所有项目的那一刻,然后在python中找到第n个最新的条目,这非常慢。

例如

class CakeType(models.Model):
name = models.CharField(max_length=40)
class CakeEntry(models.Model):
cake_type = models.ForeignKey(CakeType, on_delete=models.CASCADE)    
created = models.DateTimeField()

对于所有不同/唯一的CakeType,如何说出5个最新的CakeEntry

我将数据库从MySQL迁移到PostgreSQL(做了很多工作(,这样我就可以使用Postgres的DISTINCT ON了。

在阅读文档后,我尝试了以下操作:

from django.db.models import F, Window
from django.db.models.functions import Rank
cake_entries = (
CakeEntry.objects.order_by(
'-created'
).annotate(
rank=Window(
expression=Rank(),
partition_by=[F('cake_type_id')],
order_by=F('created').desc(),
),
).filter(rank__lt=5)
)

但是得到django.db.utils.NotSupportedError: Window is disallowed in the filter clause.如果没有秩/分区,我不确定该怎么做。

由于目标冲突,我看不到使用Window的方法:

为了解决筛选问题,必须创建一个子查询。问题是,用作表达式(注释(的子查询应该返回1行,以便将特定的秩绑定到特定的外部引用,但Window需要所有相关行的范围。图示最像这样:

# Pk 21 has rank 3
CakeEntry.objects.all().annotate(rank=rank).values("rank", "pk")[:3]
Out[11]: <QuerySet [{'pk': 2, 'rank': 1}, {'pk': 1, 'rank': 2}, {'pk': 21, 'rank': 3}]>
# Due to filter, pk 21 has rank 1, even though you seemingly filter after the annotation
CakeEntry.objects.all().annotate(rank=rank).values("rank", "pk").filter(pk=21)
Out[12]: <QuerySet [{'pk': 21, 'rank': 1}]>

我能想到的最接近的是:

class CakeEntryManager(models.Manager):
def top5_per_type(self):
cake_types = CakeType.objects.all()
qs = self.get_queryset()
results = qs.none()
for ct in cake_types:
results = results.union(qs.filter(cake_type=ct).order_by("-created")[:5])
return results.order_by("cake_type", "-created")

相关内容

最新更新