我首先尝试了一个简单的for循环的基本实现,如下图。它可以工作,但由于有10k条记录,所以耗时太长。
panoramas = Panorama.objects.all()
for panorama in panoramas:
panorama.geo_location = Point([panorama.longitude, panorama.latitude])
panorama.save()
基于Django的更新方法,我又尝试了这样的方法。
geo_location = Panorama.objects.all().update(
geo_location=fromstr(f'POINT({longitude} {latitude}', srid=4326)
)
这并不可行,因为我想让Django为每条记录选择出latlong,然后根据这两个字段更新geo_location,但Django并不知道经度和纬度是什么。
有没有一种方法可以让我用update()来实现呢?
在更新操作中使用数据库中的值正是ORM F表达式 是为了。
在文档中的例子。
这个。
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()
可以去这个。
reporter = Reporters.objects.filter(name='Tintin')
reporter.update(stories_filed=F('stories_filed') + 1)
有了这个好处 stories_filed + 1
拉,其操作(加法)在数据库处运行。
具体例子在PostGIS SQL中(未经测试)。
UPDATE
panorama
SET
geom = ST_SetSRID(
ST_Point(panorama.longitude, panorama.latitude),
4326
)
FROM
panorama
;
想出了如何批量更新 geom
字段的方式进行优化。在循环中单独保存每条记录是耗时很久的原因(如预测的那样),因此使用了django的 bulk_update()
这里的方法是需要的。Django bulk_update文档
panoramas = Panorama.objects.all()
for panorama in panoramas:
panorama.geo_location = Point(panorama.longitude, panorama.latitude, srid=4326)
Panorama.objects.bulk_update(panoramas, ['geo_location'])