2017-07-28 62 views
2

假设我有以下的数据模型如何高效是它在GeoDjango内置距离(整个表)订购

Person(models.Model): 
    id  = models.BigAutoField(primary_key=True) 
    name  = models.CharField(max_length=50) 
    location = models.PointField(srid=4326) 

假设也说我有一个应用程序,使得查询此Django的后端,而唯一这个应用程序的目的是从最近到最远返回一个(分页)注册用户列表。

目前,我有这个疑问在脑海:

# here we are obtaining all users in ordered form 
current_location = me.location 
people = Person.objects.distance(current_location).order_by('distance') 

# here we are obtaining the first X through pagination 
start_index = a 
end_index = b 

people = people[a:b] 

虽然这个工作,它是不一样快,因为我想。

我对这个查询的速度有一些担忧。如果表是大(100万+),那么就不会在数据库(SQL Postgres的W/PostGIS的)具有执行对随后一百万行的order_by之前测量数据库current_locationlocation之间的距离?

有人可以建议如何正确地返回按距离排序附近的用户以有效的方式?

回答

2

如果你想通过远程表上的每个条目进行排序,然后按预期的,并没有什么可以做,这将是缓慢的(我是在这一点上的时间和我的知识知道的。)!

您可以通过以下步骤,这样,使一些假设你的计算更高效:

  1. 启用您的表spatial indexing。要做到这一点在GeoDjango内置,请按照the doc instructions并适合你的模型:

    在PostGIS的,ST_Distance_Sphere不限制几何类型的地理距离的查询与执行。 [4]但是,这些查询可能需要很长时间,因为查询中的每一行都必须为动态计算大圆距离。这是因为传统几何领域的空间索引无法使用。

    有关WGS84距离查询,更好的性能,可以考虑在你的数据库,而不是使用geography columns,因为他们能够利用自己的空间索引中距离查询。您可以通过在字段定义中设置geography=True来告诉GeoDjango使用地理栏。

  2. 现在你可以缩小你的查询与一些逻辑约束:

    例如:我的用户将不会从他目前的位置看的人多不超过50km。

  3. 缩小搜索范围dwihin利用上述spatial indexing进行空间查找,因此速度非常快。

  4. 通过在剩余行最后应用distance顺序。

最后的查询可以是这样的:

current_location = me.location 
people = People.objects.filter(
    location__dwithin=(current_location, D(km=50) 
).annotate(
    distance=Distance('location', current_location) 
).order_by('distance') 

PS:而不是创建一个自定义分页的尝试,它是更有效的利用提供了Django的分页方法意见:

或者你可以使用Django的REST框架和使用它的分页: