Странности аннотации ArragAgg. Это ошибка или особенность?

Краткая постановка проблемы. Добавление аннотации ArrayAgg (расширения Postgres) умножает значения других аннотаций, но не всегда

Детали. Учитывая эти модели:

class MemDesc( models.Model):   

    class Meta:
        verbose_name = "Item Description"

    ... lots of data fields (Char and Integer fields)

class MemStockLineManager( models.Manager):
    def get_queryset(self):
        # always fetch related descriptions!
        return super().get_queryset().select_related('desc', 'allocated_to')

class MemStockLine( models.Model):

    class Meta:
        verbose_name="Stock Line"

    # managers. first is default 
    objects=MemStockLineManager()

    desc = models.ForeignKey( MemDesc, models.PROTECT, related_name='stock')

    ... data fields ...

class ProductCode( models.Model):
    class Meta:
        unique_together=[('code','customer'), ('customer', 'description')]

    customer = models.ForeignKey( 'customers.Customer', models.CASCADE, null=True, blank=True, )
    description = models.ForeignKey( MemDesc, models.CASCADE, )
    code = models.CharField( max_length = 20)

Я не думаю, что MemStockLineManager имеет значение, но я включил его на всякий случай.

Может ли кто-нибудь объяснить эти результаты? Это, как и ожидалось:

>>> from django.db.models import Q,F, Sum, Count
>>> from django.db.models.functions import Coalesce
>>> from django.contrib.postgres.aggregates import StringAgg, ArrayAgg

>>> qsx = MemDesc.objects.all().annotate( stocklines= Coalesce( Count('stock__qty'), 0), 
... stocklevel= Coalesce( Sum('stock__qty'), 0))
>>> qs1 = qsx.filter(pk=140); o = list(qs1)[0]; o.stocklines
11
>>> o.stock.count()
11

Добавьте аннотацию ArrayAgg, аннотация stocklines удваивается.

>>> qsx = MemDesc.objects.all().annotate( stocklines= Coalesce( Count('stock__qty'), 0), 
... stocklevel= Coalesce( Sum('stock__qty'), 0) ,
... partnumbers=ArrayAgg('productcode__code', distinct=True))
>>> qs1 = qsx.filter(pk=140); o = list(qs1)[0]; o.stocklines
22
>>> o.stock.count()
11
>>> o.partnumbers
['Anybody001', 'TEST0001']

но, похоже, только когда аннотация массива является множественной:

>>> qs1 = qsx.filter(pk=168); o = list(qs1)[0]; o.stocklines
4
>>> o.stock.count()
4
>>> o.partnumbers
[None]

>>> qs1 = qsx.filter(pk=128); o = list(qs1)[0]; o.stocklines
2
>>> o.stock.count()
2
>>> o.partnumbers
['Foo123']

Есть ли способ обойти это? Я пытаюсь избежать проблемы N+1, которая возникает, если у меня нет всех этих аннотаций и мне приходится делать запрос для каждой строки/объекта в том, что фактически является ListView.

Вернуться на верх