Оптимизируйте набор запросов с помощью Django - PullRequest
0 голосов
/ 30 мая 2018

Я создал функцию, которая позволяет подсчитать число status и присвоить его переменной.

def get_types_count_display(self):
    dispatches = self.route_dispatches.values_list('dispatch_id', flat=True)
    dispatches = Dispatch.objects.filter(id__in=dispatches)
    d = { "dispatches_types": list(dispatches.values('status_id')) }
    pendents = len([1 for e in d["dispatches_types"] if e["status_id"]==1])
    delivered = len([1 for e in d["dispatches_types"] if e["status_id"]==2])
    partial = len([1 for e in d["dispatches_types"] if e["status_id"]==3])
    undelivered = len([1 for e in d["dispatches_types"] if e["status_id"]==4])
    return dict(pendents=pendents, delivered=delivered, partial=partial, undelivered=undelivered)

, где d - моя переменная, в которой хранится содержащийся в ней словарь

{'dispatches_types': [{'status_id': 2}, {'status_id': 1}, {'status_id': 1}, {'status_id': 1}, {'status_id': 2}]}

или

{'dispatches_types': []}

это динамически

проблема, с которой я столкнулся, заключается в том, что когда вы снова набираете for, снова вызываетенабор запросов, запрос становится тяжелее.

Как я могу оптимизировать эту функцию?

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Для «менее» запросов вы можете использовать условное агрегирование .Данный пример - практически то, что вы пытаетесь сделать.

Если общее количество записей Dispatch относительно невелико, загрузите все это сразу в память (как, скажем, словарь, вызвав .values() нанабор запросов), а затем его фильтрация может быть быстрее, чем получение фрагментов записей за цикл.Я делаю это довольно часто, особенно если это означает избегать создания экземпляров объектов модели.

- кажется, я был слишком медленным!

0 голосов
/ 30 мая 2018

Как уже было сказано, условное агрегирование может работать лучше здесь.Просто хотел добавить альтернативный запрос, так как нам не нужно получать суммирование, а количество отправлений с указанным статусом.Так что это можно записать так:

from django.db.models import Q


aggregates = dispatches.aggregate(
    pendents=Count('pk', filter=Q(status_id=1)),
    delivered =Count('pk', filter=Q(status_id=2)),
    partial=Count('pk', filter=Q(status_id=3)),
    undelivered=Count('pk', filter=Q(status_id=4)),
)
0 голосов
/ 30 мая 2018

Для этого следует использовать условное агрегирование

from django.db import IntegerField, Sum, Case, When

def get_types_count_display(self):
    dispatches self.route_dispatches.all()
    aggregates = dispatches.aggregate(
        pendents=Sum(Case(When(status_id=1, then=1), output_field=IntegerField())),
        delivered =Sum(Case(When(status_id=2, then=1), output_field=IntegerField())),
        partial=Sum(Case(When(status_id=3, then=1), output_field=IntegerField())),
        undelivered=Sum(Case(When(status_id=4, then=1), output_field=IntegerField()))
    )
    return aggregates 

aggregates - это диктовка с теми же значениями, которые вы возвращали ранее, но выполнялась с 1 запросом

...