Фильтр Django QuerySet получает последний объект перед обрезанием date_time - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь сохранить QuerySet ленивым (не оцененным) при его создании, и цель, которую я имею, - найти последнее событие до заданной даты.

class Event(models.Model):
    date_time = models.DateTimeField('Date and time of event')

    class Meta:
         ordering = ['-date_time']

Теперь у меня есть date_time cut_off, и я могу легко получить все События после этого отключения с помощью:

events = Event.objects.filter(date_time__gte=cut_off)

Теперь я хотел бы включить последнее Событие до cut_offа также!

Я могу придумать несколько способов сделать это, которые вызовут хиты базы данных, но я бы хотел найти решение, которое поддерживает QuerySet ленивым.

Очевидным кандидатом является функция задержки окна.Если мы аннотируем события с помощью date_time следующего события, что-то вроде этого концептуально работает:

window_lag = Window(expression=Lag("date_time"),
                    order_by=F("date_time").desc())

annotated_events = Event.objects.annotate(date_time_next=window_lag)
events = annotated_events.filter(date_time_next__gte=cut_off)

Но, увы, это недопустимо (пока):

https://code.djangoproject.com/ticket/28333

Это может быть сделано (и я сделал это) с использованием необработанного SQL, но опять же, ой.Я хотел бы сохранить это как можно более чистым, а QuerySet - ленивым (база данных не удастся создать).

Существует ли какой-либо творческий способ написания фильтров, которые не используют оконные функции, могут оставаться ленивыми и при этом достигатьжелаемый результат возврата всех событий после cut_off и непосредственно перед ним?

Мы не знаем, сколько времени прошло между этим событием и датой cut_off, может быть секундами, может быть годами, без предположенийвозможно там, все, что мы знаем, это следующее ... это все.

Возможно, что-то со структурой вроде:

events = Event.objects.filter(Q(date_time__gte=cut_off)|Q(...))

, где второй объект Q как-то творчески добавляет желаемое событие.

1 Ответ

0 голосов
/ 04 июля 2019

Оказывается, это не совсем выполнимо с одними объектами Q, но с объединением это:

events = Event.objects.filter(date_time__gte=cut_off)
extra_event = Event.objects.filter(date_time__lt=cut_off)[:1]
events = events.union(extra_event)

Это все еще ленивая и элегантная реализация ORM.

Я не уверен, как это сравнивается с точки зрения производительности с использованием аннотации Window Lag, но до тех пор, пока это не будет отфильтровано в Django, это не элегантный вариант ORM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...