Postgresql上带order_by、distinct和limit的Django查询

Postgresql上带order_by、distinct和limit的Django查询,django,postgresql,django-queryset,Django,Postgresql,Django Queryset,我有以下资料: class Product(models.Model): name = models.CharField(max_length=255) class Action(models.Model): product = models.ForeignKey(Product) created_at = models.DateTimeField(auto_now_add=True) 我想检索由created_at DESC订购的10项最新操作,这些操作具有不同的产

我有以下资料:

class Product(models.Model):
    name = models.CharField(max_length=255)

class Action(models.Model):
    product = models.ForeignKey(Product)
    created_at = models.DateTimeField(auto_now_add=True)
我想检索由created_at DESC订购的10项最新操作,这些操作具有不同的产品

以下内容与结果接近,但仍未排序:

Action.objects.all().order_by('product_id').distinct('product_id')[:10]

编辑:此解决方案有效,但Ross Lote的更干净

这就是我最终的做法,使用:

通过设置
值(“产品id”)
我们对产品id进行分组

使用
annotate()
我们只能在
values()
annotate()
中使用的字段上使用order\u by。由于对于每个操作,created_at字段自动设置为now,因此在created_at上排序与在id上排序相同,使用
注释(action_id=Max('id'))。按('-action_id')
排序是正确的方法

最后,我们只需要对查询进行切片
[:10]


希望这能有所帮助。

您的解决方案似乎做得太多了。它还将导致两个单独的SQL查询。这将很好地工作,并且只需要一个查询:

action_ids = Action.objects.order_by('product_id', '-created_at')\
    .distinct('product_id').values_list('id', flat=True)

result = Action.objects.filter(id__in=action_ids)\
    .order_by('-created_at')[:10]

您是否尝试过颠倒
order\u by()
distinct()
调用的顺序?Django的文档说明:“指定字段名时,必须在QuerySet中提供order\u by(),order\u by()中的字段必须以distinct()中的字段开头,顺序相同。”。您的订单是通过
product\u id
,而不是在
创建的
。为什么?因为为了使distinct('product_id')起作用,您必须在order_by子句中指定它。但是,您可以有多个参数来order_by。根据他们刚才提供的链接示例,您似乎可以这样做:
.order\u by('product\u id','created\u at')。distinct('product\u id')
使用'values\u list'是一个好主意,因为它可以保存一个查询。我相应地编辑了我的答案。你试过运行我的代码吗?第一行将正常运行,因为第一个
order\u by
distinct
是相同的。在
创建的第一个
-确保您只能获得每个产品的最新操作(此时,它们的顺序可能不正确)。第二行只是将操作按正确的顺序排列,但仍然保持在相同的查询中。感谢您的解释,您是对的!你的代码运行得很好,比我的好!谢谢:)我仍然不明白为什么我们不能只在一行中这样做,比如
Action.objects.order\u by('product\u id','-created\u at')。distinct('product\u id')[:10]
。我之所以这么说是因为我试图使用
.distinct(…).filter(…)
,而且似乎过滤器是在distinct之前“执行”的。。。
action_ids = Action.objects.order_by('product_id', '-created_at')\
    .distinct('product_id').values_list('id', flat=True)

result = Action.objects.filter(id__in=action_ids)\
    .order_by('-created_at')[:10]