【问题标题】:How to get latest n record for per group in Django Orm如何在 Django Orm 中获取每个组的最新 n 记录
【发布时间】:2018-06-14 04:46:46
【问题描述】:

我有 3 个类似的模型

class Business(models.Model):
    name = models.CharField(max_length=30)
    ...

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    date = models.DatetimeField()
    business = models.ForeignKey(Business)

我想得到每个家伙的最后 3 个电话号码,这就是我实现它的方法;

response=list()
for dude in Dude.objects.all():
    temp_dude = dict()
    temp_dude['name_label'] = str(dude.name)
    temp_dude['phones'] = list()
    for phone_number in PhoneNumber.objects.filter(dude=dude).order_by("-date")[:3]:
        temp_phone = dict()
        temp_phone['date_added'] = phone_number.date.timestamp()
        temp_phone['business_label'] = str(phone_number.business.name)
        temp_dude['phones'].append(temp_phone)
    response.append(temp_dude)

但是对于每个人来说,它至少要访问数据库 2 次,并且消耗大量的 cpu。

用 django orm 获得相同响应的最有效方法是什么?

P.S : 我有 3000 万个电话号码和 170 个哥们。

【问题讨论】:

  • 尝试在模型类中排序?
  • 问题不在于获取项目,而是遵循循环中的外键。试试docs.djangoproject.com/en/2.0/ref/models/querysets/…!
  • 问题之一是在 MySQL 中没有直接的方法来限制 per group。是的,你可以通过一些黑客来做到这一点,但没有特殊的语法。
  • @WillemVanOnsem 我正在使用 postgresql,但如果可以的话,我想用 orm 来实现。

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


【解决方案1】:

在这种情况下,首先要尝试使用select_related 来获取每个人的电话号码。

dudes = Dude.objects.select_related('phone_number', 'phone_number__business').all()
for dude in dudes:
    do_the_thing()  

(注意您正在查询的另一个对象上的select_related,phone_number.business)

在这种情况下,如果每个 Dude 有很多 phone_numbers,那么这可能会比您的原始查询执行得更差,因为它会获取每个 Dude.phone_number。

不幸的是,正如 cmets 所建议的,没有 ORM 方法来限制 select_related。您需要编写一些 SQL。您可以通过打开 DB kogging 来观察 SQL Django 为 select_related 查询生成的内容,然后运行您自己的 custom SQL query,从而抢占先机。

【讨论】:

    猜你喜欢
    • 2022-12-07
    • 2013-07-27
    • 2016-11-26
    • 1970-01-01
    • 2019-10-11
    • 1970-01-01
    • 2013-11-24
    相关资源
    最近更新 更多