Как получить первичный ключ аннотационного графа

Привет сообщество stackoverflow, мой вопрос касается django annotate.

В основном я пытаюсь найти дублирующееся значение с одинаковыми значениями из двух разных полей в двух разных таблицах.

Это мой models.py

class Order(models.Model):
    id_order = models.AutoField(primary_key=True)
class OrderDelivery(models.Model):
    order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True, blank=True)
    delivery_address = models.TextField()
class OrderPickup(models.Model):
    order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True, blank=True)
    pickup_date = models.DateField(blank=True, null=True)

Вот мой текущий код:

dup_job = Order.objects.filter(
        orderpickup__pickup_date__range=(start_date, end_date)
    ).values(
        'orderdelivery__delivery_address',
        'orderpickup__pickup_date',
    ).annotate(
        duplicated=Count('orderdelivery__delivery_address')
    ).filter(
        duplicated__gt=1
    )

На основании того, что у меня есть, я получаю такой результат (адрес доставки опущен в целях конфиденциальности):

{'orderdelivery__delivery_address': '118A', 'orderpickup__pickup_date': datetime.date(2022, 3, 9), 'duplicated': 2}
{'orderdelivery__delivery_address': '11', 'orderpickup__pickup_date': datetime.date(2022, 3, 2), 'duplicated': 6}
{'orderdelivery__delivery_address': '11 A ', 'orderpickup__pickup_date': datetime.date(2022, 3, 3), 'duplicated': 5}
{'orderdelivery__delivery_address': '21', 'orderpickup__pickup_date': datetime.date(2022, 3, 10), 'duplicated': 3}
{'orderdelivery__delivery_address': '642', 'orderpickup__pickup_date': datetime.date(2022, 3, 7), 'duplicated': 2}
{'orderdelivery__delivery_address': '642', 'orderpickup__pickup_date': datetime.date(2022, 3, 8), 'duplicated': 2}
{'orderdelivery__delivery_address': 'N/A,5', 'orderpickup__pickup_date': datetime.date(2022, 3, 8), 'duplicated': 19}

Есть ли способ получить id_order тех, кто "дублируется"? Я пробовал включить id_order в .values(), но результат не будет точным, так как аннотация группируется по id_order, а не по delivery_address.

Заранее благодарю

Вы можете получить наименьший (или наибольший) элемент с помощью Min [Django-doc] (или Max) агрегата:

from django.db.models import Min

dup_job = Order.objects.filter(
    orderpickup__pickup_date__range=(start_date, end_date)
).values(
    'orderdelivery__delivery_address',
    'orderpickup__pickup_date',
).annotate(
    min_id_order=Min('id_order')
    duplicated=Count('orderdelivery__delivery_address')
).filter(
    duplicated__gt=1
)

или для , вы можете воспользоваться ArrayAgg [Django-doc] для создания списка:

# PostgreSQL only

from django.contrib.postgres.aggregates import ArrayAgg

dup_job = Order.objects.filter(
    orderpickup__pickup_date__range=(start_date, end_date)
).values(
    'orderdelivery__delivery_address',
    'orderpickup__pickup_date',
).annotate(
    min_id_order=ArrayAgg('id_order')
    duplicated=Count('orderdelivery__delivery_address')
).filter(
    duplicated__gt=1
)
Вернуться на верх