Django ORM: упорядочение с агрегатными функциями - нет специальной обработки - PullRequest
1 голос
/ 03 апреля 2010

Я делаю этот запрос:

SomeObject.objects.annotate(something=Avg('something')).order_by(something).all()

Обычно в моей модели есть агрегатное поле, которое я использую с сигналами Django для синхронизации, однако в этом случае производительность не является проблемой, поэтому я решил, что я буду прост и просто использую подзапросы.

Однако такой подход вызвал неожиданную проблему. Все это прекрасно работает, если результаты агрегатной функции имеют вид:

[5.0, 4.0, 6.0 … (etc, just numbers)]

Однако, если вы смешаете в некоторых None, чем это упорядочено следующим образом:

[None, 5.0, 4.0 …]

Проблема в том, что None имеет более высокое значение, чем любое число, в то время как оно должно иметь значение не более 0.

Я использую PostgreSQL и не тестировал другие БД. На самом деле я не проверял, какой запрос генерируется и т. Д.

Я обошел это, просто отсортировав в памяти:

sorted(…, key=lambda _:_.avg_rating if _.avg_rating is not None else 0) 

Так что мне просто интересно, есть ли способ сделать это только с помощью Django ORM? Возможно .where? Или что-то еще?

1 Ответ

2 голосов
/ 04 апреля 2010

Как насчет простого добавления has_something = 1,0 с помощью extra () и последующего заказа на has_something и что-то еще?

with_avg = SomeObject.objects.annotate(avg=Avg('something'))
with_avg_and_has = with_avg.extra(select={'has_something': 'something is NULL'})
sorted_result = with_avg_and_has.order_by('-has_something', '-avg').all() 

Не 100% ORM в самом строгом смысле, но оно толкает сортировку обратно в БД.

...