2014-02-13 21 views
0

當我最需要它時,堆棧幫了我大忙,我要再次測試我的運氣。這是場景。目前我有以下型號:關於如何使用Django和PostgreSQL構建位置模型的建議(postGIS)

class Location(models.Model): 
    name = models.CharField(max_length=200, blank=True) 
    address = models.CharField(max_length=255, blank=True) 
    city = models.CharField(max_length=140, null=True, blank=True) 
    province_state = models.CharField(max_length = 140, null=True, blank=True) 
    country = models.CharField(max_length=2, null=True, blank=True) 
    postal_code = models.CharField(max_length=32, null=True, blank=True) 
    foursquare_id = models.CharField(max_length=100, blank=True, unique=True) 
    lat = models.DecimalField(max_digits=18, decimal_places=15, null=True, blank=True) 
    lon = models.DecimalField(max_digits=18, decimal_places=15, null=True, blank=True) 

看起來挺直挺的吧?現在我所做的是返回位於用戶當前位置100公里範圍內的所有位置。每個學位大約100公里。例如,在10度到11度的緯度之間,距離100公里。與經度相同。 1度約爲100公里。這是我的看法WhatsNearBy:

@csrf_exempt 
def WhatsNearBy(request): 
    if request.META.has_key('HTTP_AUTHORIZATION') and request.method == 'GET': 
     authmeth, auth = request.META['HTTP_AUTHORIZATION'].split(' ', 1) 
     if authmeth.lower() == 'basic': 
      auth = auth.strip().decode('base64') 
      username, password = auth.split(':', 1) 
      authuser = authenticate(username=username, password=password) 
      if authuser: 
       if authuser.is_active: 
       client_lat = int(request.GET.get('lat')) 
       client_lon = int(request.GET.get('lon')) 

       queryset = Location.objects.filter(__lat__gte = (client_lat - 1), 
           lat__lte = (client_lat + 1), 
           lon__gte = (client_lon - 1), 
           lon__lte = (client_lon + 1)) 
       return queryset 

以上的查詢集返回所有大約100公里的位置。這工作很好,而且非常穩固。但是,我擔心的是隨着數據庫變大,過濾遲早會變慢。

我聽說過有關postGIS,但我不確定它是否會比我現在做的更有效率。我需要將位置模型遷移到postGIS嗎?這一切如何工作?一旦我做到了,我能夠在一定距離內找到所有的位置?

期待看到您的解決方案!

回答

1

我最近處理了一個類似的問題。我發現PostGIS和其他空間解決方案對於在近似半徑內查找所有點是過度殺傷性的。

我結束了在數據庫中使用SAS距離算法。使用正方形過濾後,我使用raw命令讓數據庫爲我編寫數字。 Postgres和除SQLite以外的大多數其他數據庫都支持trig函數,因此您可以過濾數據庫的計算距離。這是以英里爲單位的公式,但您可以更改常數。

Dist = 3949.99 * arcos(sin(Y1) * sin(Y2) + cos(Y1) * cos(Y2) * cos(X1 - X2)); 

http://support.sas.com/kb/3/973.html

編輯:要展開,我被查詢半徑內的所有美國郵政編碼(〜44K)。事實證明,我可以在幾分之一秒內查詢500英里內的所有郵政編碼,這些郵政編碼對於我的目的來說是可接受的。地理空間庫允許您更快速地找到複雜多邊形內的所有點,但我不指望您會看到應用程序顯着的性能改進。

+0

感謝您的回覆! – noahandthewhale