2009-12-05 128 views
2

我想實現基於經度和使用Django和Postgresql的鄰近搜索。這是我擁有的模型的抽象版本。Django模型屬性地理距離

class Item(models.Model): 
"""docstring for Item""" 
uuid = UUIDField(primary_key=True, auto=True) 
name = models.CharField(_("name"), max_length=200) 
address = models.CharField(_('street address'), max_length=255, blank=True, null=True) 
location = models.CharField(_('location'), max_length=40, blank=True, null=True) 

@property 
def geo_distance(self, location=None): 
    if location is not None: 
     cursor = connection.cursor() 
     cursor.execute("SELECT geo_distance(CAST('%s')) AS POINT, CAST('%s') AS POINT)" % 
      self.location, location) 
     return round(float(cursor.fetchone() * 1.621371192237), 2) 

我希望能夠做這樣的事情在views.py:

items = Item.objects.filter(name__istartwith="Anything") 
results = [] 
for item in items: 
    results.append({ 
     'name': item.name, 
     'distance': item.geo_distance("(11.23123, -12.123213)") 
    }) 

我知道這是不是最好的方法。歡迎任何建議。

+2

你可能想用geodjango和geopy來標記它。 – 2009-12-06 00:07:01

回答

2

如果你基於經緯度搜索,我會建議你GeoDjango。要計算從X點開始的兩點或周圍區域之間的距離,可以使用Haversine formula。最好使用procedure來編寫距離計算。據我所知,Django不支持創建程序,我在計算距離方面做了一些基準測試,我發現程序更快,而不是在Django端進行計算。祝你好運。

+1

感謝Prashanth的建議。我一定會深入研究GeoDjango。就目前而言,我使用了Geopy來解決我的問題。其地理編碼和距離計算模塊相當有用。 – Nav 2009-12-07 02:23:43

1

那麼,你的代碼並不可怕。我想你是關心性能的,因爲item.geo_distance()在iteration中執行?這並不重要,這將不得不在一段時間內計算。您的解決方案是好的,但這裏有一些其他指針:

  • 使用geopy(或GeoDjango內置)
  • 務必在源(數據庫)來過濾數據。

關於第二點,過濾你的數據。我看到你正在過濾名稱,這意味着你沒有使用過濾距離。如果你確實想使用距離某個點的距離作爲過濾器(例如,不超過40英里),那麼你會遇到geopy和geodjango可以提供幫助的一些新問題。這裏常見的解決方案是近似距離(以平方爲單位),根據此近似值過濾數據,然後計算精確距離。

+0

感謝marcc花時間。 Geopy似乎是我需要的,我已經將它融入到我的項目中。 我忘了將geo_distance作爲過濾器,但這是其中一個要求。我使用Geopy的距離計算模塊完成了這項工作。與Geopy相比,在數據庫級別對其進行過濾似乎不準確,而且速度比幾百毫秒慢。 – Nav 2009-12-07 02:35:11

+0

不錯!幾個月前,我完成了一個django/geopy項目。使用geopy計算來爲iPhone應用程序使用的API提供動力。奇蹟般有效。 – marcc 2009-12-07 05:53:50