Итак, моя проблема в плохом понимании сложности моего запроса. Немного предыстории этого вопроса.
Это сайт по прокату и поиску автомобилей, который начался как мой личный проект. Для этого я использую Django 2.1, а также Postgres.
Настройка выглядит следующим образом: у меня есть модель автомобиля с идентификатором, категорией, типом автомобиля, двигателем и т. Д. Во-вторых, есть таблица адресов, которую я использую для всех видов вещей.
Теперь я хотел бы сделать следующее:
Я хочу создать специфичные для Google Ads файлы .csv. Этот файл нуждается в определенном столбце с агрегированными целыми числами, чтобы показать «связанный контент» для пользователя. Значение: Вы видели Автомобиль A, здесь представлен список похожих или похожих автомобилей в этой области: Автомобиль K, O и Q.
У меня действительно нет проблем с созданием csv из моих данных, но моя проблема скорее в том, чтобы создать запрос, чтобы это работало. В качестве первого шага у меня есть следующее:
cars = Car.objects
.select_all_related()
.only(
'id',
'name',
'address__city',
'address__city_area',
'images'
)
1
select_all_related
присоединяется к таблице адресов, потому что там находится машина. Это также заставляет мой вызов only () работать, так как я хочу вытащить определенные поля
Выбрать ссылку на соответствующий документ
2
дает мне только те поля, которые я хочу, так как я не хочу отправлять всю модель в любом случае, это также работает.
Только справочный документ
Таким образом, выбор и получение правильных данных не проблема, но:
Реальная проблема:
Следующий код должен создать столбец в таблице. В этом столбце должны быть агрегированные идентификаторы автомобилей, которые находятся в аналогичной области (город и район города). И это, к сожалению, требование Google Ads, которым я пользуюсь.
def find_similiar_cars_in_same_city(cars: QuerySet):
"""Annotate the QuerySet with a field called similar_cars_ids containing
a list of ad IDs or None if there are none."""
similar_cars_queryset = Cars.objects.filter(
address__city=OuterRef('address__city'),
address__city_area=OuterRef('address__city_area'),
).exclude(id=OuterRef('id')).values_list(ArrayAgg('id'), flat=True)
# Hack: Remove GROUP BY that Django adds when adding ArrayAgg.
similar_cars_queryset.query.group_by = []
cars = cars.annotate(similar_cars_ids=Subquery(
similar_cars_queryset,
output_field=ArrayField(models.IntegerField())
))
return cars
И это вроде работает. просто берет навсегда. Вы также можете увидеть комментарий, который я сделал в коде, что annotate () на самом деле группирует, по которому я действительно не хочу здесь. Я управляю всем на месте, и даже наличие 10 машин занимает около 12 секунд Я не уверен, что я что-то упустил. Это вроде работает, но не будет работать для большего размера выборки. Я столкнулся с БД с примерно 14 тысячами машин, и он так и не закончился.
Итак, подведем итог: я хочу создать функцию, которая создает в БД столбец с агрегированными идентификаторами похожих автомобилей.
У кого-нибудь есть указатель на то, где это сделать эффективнее? И, пожалуйста, спросите, есть ли еще вопросы, и я забыл кое-что упомянуть!