【发布时间】:2019-03-25 17:57:51
【问题描述】:
所以我的问题来自对查询复杂性的理解不足。这个问题的背景故事。
这是一个汽车租赁和搜索网站,最初是我的个人项目。我为此使用 Django 2.1 以及 Postgres。
设置如下:我有一个车型,它有一个ID、一个类别、一个车型、一个引擎等。其次,有一个地址表,我用它来做各种各样的事情。
我现在想做的是:
我想创建特定于 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
只给我我想要的字段,因为我不想发送整个模型,这也有效。
所以选择和获取正确的数据不是问题,而是:
真正的问题:
以下代码应在表中创建一列。此列应具有相似区域(城市和市区)中汽车的聚合 ID。遗憾的是,这是我使用的 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 秒。我不确定我是否遗漏了什么。它有点工作,但不适用于更大的样本量。我在一个大约有 14k 辆汽车的数据库上运行它,但它从未完成。
总结一下:我想创建一个函数,在数据库中创建一个包含相似汽车的聚合 ID 的列。
任何人都知道在哪里可以提高效率?如果还有其他问题,请询问,我忘了提一些事情!
【问题讨论】:
标签: python django postgresql orm aggregate-functions