【发布时间】:2019-12-07 13:33:18
【问题描述】:
我的 Django 项目中有下一个模型:
class Area(models.Model):
name = models.CharField(_('name'), max_length=100, unique=True)
...
class Zone(models.Model):
name = models.CharField(verbose_name=_('name'),
max_length=100,
unique=True)
area = models.ForeignKey(Area,
verbose_name=_('area'),
db_index=True)
polygon = PolygonField(srid=4326,
verbose_name=_('Polygon'),)
...
Area 就像一个城市,Zone 就像一个区。
所以,我想为每个区域缓存其区域内其他区域的顺序。像这样的:
def store_zones_by_distance():
zones = {}
zone_qs = Zone.objects.all()
for zone in zone_qs:
by_distance = Zone.objects.filter(area=zone.area_id).distance(zone.polygon.centroid).order_by('distance').values('id', 'name', ...)
zones[zone.id] = [z for z in by_distance]
cache.set("zones_by_distance", zones, timeout=None)
但问题是它效率不高且不可扩展。我们有 382 个区域,这个函数获取 383 个对 DB 的查询,而且速度很慢(SQL 时间为 3.80 秒,全局时间为 4.20 秒)。
是否有任何有效且可扩展的方法来获得它。我曾想过这样的事情:
def store_zones_by_distance():
zones = {}
zone_qs = Zone.objects.all()
for zone in zone_qs.prefetch_related(Prefetch('area__zone_set', queryset=Zone.objects.all().distance(F('polygon__centroid')).order_by('distance'))):
by_distance = zone.area.zone_set.all().values('id', 'name', ...)
zones[zone.id] = [z for z in by_distance]
这显然不起作用,但是像这样,在 SQL 中缓存(与预取相关)排序的区域(area__zone_set)。
EDIT store_zones_by_distance 将返回(或设置在缓存中)如下内容:
{
1: [{"id": 1, "name": "Zone 1"}, {"id": 2, "name": "Zone 2"}, {"id": 2, "name": "Zone 4"}, {"id": 2, "name": "Zone 3"}],
2: [{"id": 2, "name": "Zone 2"}, {"id": 2, "name": "Zone 4"}, {"id": 2, "name": "Zone 1"}, {"id": 2, "name": "Zone 3"}],
...
}
【问题讨论】:
标签: python django gis postgis geodjango