Поиск последней даты в объекте Django Q - PullRequest
1 голос
/ 24 октября 2019

Не на 100% доволен структурой этого кода, но, к сожалению, я не могу сейчас его изменить. Я ищу большую базу данных в Django, и из-за технических ограничений я должен сохранить список Q объектов и использовать функцию reduce() Django для объединения Q объектов в один Queryset. В настоящее время у меня есть такая модель:

class Obj(models.Model):
    id_number = models.CharField(max_length=128)
    modified = models.DateField('%Y-%m-%d', default='1900-01-01')

В настоящее время я использую следующий код для выбора строк, в списке которых присутствует id_number, latest_ids:

split_queries = []
for id_num in latest_ids:
    split_queries.append(Q(id_number=id_num))
result = Obj.objects.filter(reduce(operator.or_, split_queries))

Это работает, как я и ожидал, но я хотел бы сохранить только строку, в которой id_number=id_num и дата modified являются самыми последними. Я видел такие решения, как использование функции aggregate() Джанго или функции latest(), но я не могу понять, как использовать их с объектами Q. Я надеялся, что Q объект, такой как

Q(id_number=id_num, Max('modified'))

, возможно ли такое поведение с Q объектами в Django?

EDIT Система, которой я являюсьработая над использует SQLite. База данных велика, и в прошлом проблемы решались с помощью Too Many SQL variables (SQLite позволяет только 1000), а для запросов, в которых выбрано много id_number с, разбиение запроса на более мелкие группы объектов Q решило эти проблемы. .

База данных имеет много разных id_number с, но многие строки имеют одинаковые id_number с. Я хотел бы иметь возможность для каждого из latest_id с выбрать одну строку, соответствующую этому id_number и имеющую самую последнюю дату modified (или несколько строк, если даты совпадают).

1 Ответ

1 голос
/ 24 октября 2019

Я не понимаю вашего Q во-первых. Obj.objects.filter(id_number__in=latest_ids) дает вам строки, где id_number является одним из latest_ids.

РЕДАКТИРОВАТЬ: кажется, вам нужно сохранить запросы Q () для вашего варианта использования. В этом случае невозможно добавить то, что вы хотите внутри фильтра Q ().

Но группировка и аннотирование полученного запроса могут не быть такой проблемой. Попробуйте это:

Obj.objects.filter(reduce(operator.or_, split_queries))\
    .values('id_number').annotate(latest_modified=Max('modified'))
...