2017-07-28 28 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框架和使用它的分頁: