Django通过查询集中的唯一值获取总计数和计数

Posted

技术标签:

【中文标题】Django通过查询集中的唯一值获取总计数和计数【英文标题】:Django get total count and count by unique value in queryset 【发布时间】:2021-01-02 06:28:58 【问题描述】:

我的模型 SoftwareDomain 大致描述为:

class Software(models.Model)
    id = models.BigInteger(primary_key=True, db_index=True, null=False)
    company = models.ForeignKey('Company')
    domain = models.ForeignKey('Domain')
    type = models.CharField(null=False)
    vendor = models.CharField(null=False)
    name = models.CharField(null=False)

class Domain(models.Model):
    id = models.BigInteger(primary_key=True, db_index=True, null=False)
    type = models.CharField()
    importance = models.DecimalField(max_digits=11, decimal_places=10, null=False)

我得到一个 Software 查询集:

qs = Software.objects.filter(company=c).order_by('vendor')

所需的输出应具有聚合的 Domain 重要性以及每个唯一 Software 的总计数,即

[
  
    'type': 'type_1',  \
    'vendor': 'ajwr',   | - unique together
    'name': 'nginx',   /
    'domains': 
      'total_count': 4, 
      'importance_counts': [0.1: 1, 0.5: 2, 0.9: 1] # sum of counts = total_count
    ,
  ,
  
    ...
  ,
]

我觉得这里的第一步应该是将type, vendor, name 分组Domain 这样每个Software 对象都有一个Domains 列表而不是一个列表,但我不知道该怎么做.在内存中执行此操作会更容易,但似乎比使用查询集/SQL 慢很多。

【问题讨论】:

这看起来更像是序列化程序的工作(就像你说的,在 python 中做)但是为了确保你避免做很多数据库查询,你应该使用.prefetch_related('domain') 我认为 WRT 在内存中这样做是对的——尽管我觉得在 Domain backSoftware 上存在一对多关系,它可以在单独的查询集 【参考方案1】:

所以我会这样做:

from django.db.models import Sum
qs = Software.objects.filter(company=c).prefetch_related(
        'domain'
     ).annotate(
        total_count=Sum('domain__importance')
     ).order_by('vendor')
output = []
for obj in qs:
    domains = obj.domain.all() # using prefetched domains, no db query
    output.append(
        # ...
        'domains': 
            'total_count': obj.total_count,
            'importance_counts': [d.importance for d in domains]
        
    )

而且我相信它应该足够快。只有当发现它不是我会尝试改进。记住“过早的优化是万恶之源”

【讨论】:

以上是关于Django通过查询集中的唯一值获取总计数和计数的主要内容,如果未能解决你的问题,请参考以下文章

在 django 的查询集中获取对象的计数

是否有任何其他选项可以从表中获取总计数和同一查询中列的不同计数?

如何使用 sql 中的单个查询获取项目计数和总计数?

如何处理 django 查询集中的变量字符串?

有没有办法在单个 psql 查询中返回总计数和行数?

分页问题:返回正文中的总计数和总页数,而不添加到正在获取的其他数据