Django 2.1+批量更新记录及其相关记录的数量?

时间:2019-04-24 09:16:53

标签: python django postgresql

我正尝试使用表B中相关记录的数量来批量更新表A中的所有记录。

我想做类似的事情:

from django.db.models import Subquery, OuterRef, Count


table_b_subquery = TableB.objects.filter(a_id=OuterRef('id'))

TableA.objects.all().update(table_b_count=Count(Subquery(table_b_subquery)))

这等效于此NON-BULK方法:

# Non-Bulk

for record in TableA.objects.all():
  record.table_b_count = record.table_b_set.count()

我尝试使用批量方法的错误是:

*** django.core.exceptions.FieldError: Aggregate functions are not allowed in this query

在批量更新中,如何看似简单地计算相关记录?理想情况下,我也想对表B的数量应用一个简单的字段过滤器。

2 个答案:

答案 0 :(得分:1)

您需要一个用于计数的子查询(而不仅仅是可计数的对象),这有点麻烦,因为像count()aggregate()这样的常规聚合查询往往会立即执行,而子查询则需要懒惰。这就是为什么需要以下annotate()解决方法:

from django.db.models import Subquery, OuterRef, Count

table_b_subquery = Subquery(TableB.objects
    .filter(a_id=OuterRef('id'))
    .values('a_id')
    .annotate(cnt=Count('a_id'))
    .values('cnt')
)

TableA.objects.update(table_b_count=table_b_subquery)

答案 1 :(得分:0)

Endre的答案就是我想要的!我刚刚在Django 2.2中发现了一个可能值得使用的新功能,但我很矛盾。我不确定哪个更好。

Django 2.2具有bulk_update

https://docs.djangoproject.com/en/2.2/ref/models/querysets/#django.db.models.query.QuerySet.bulk_update

因此,我以bulk_update为题,

records = []
for record in TableA.objects.all():
  counted_record = record.table_b_count = record.table_b_set.count()
  records.append(counted_record)

TableA.objects.bulk_update(records, ['table_b_count'], batch_size=100000) 

# This is acting on Table A with 1,000,000 rows and Table B with 5,000,000 rows.

在这种情况下,有成千上万的行,是否有人对Endre的答案或新的Django 2.2方法更好?