2014-12-04 74 views
0

編輯:增加了更好的描述空間搜索到多點

我使用的Django乾草堆2.3.1 Elasticsearch後端,Django的1.7和Python 3.4

在我的應用程序有一個供應商模式和一個位置模型。位置包含完整的美國郵政地址,緯度/經度和GEOS點對象。供應商擁有包含位置的ManyToManyField,保持多個供應商可以在一個位置可用,並且一個位置可以爲多個供應商提供服務。當用戶搜索供應商時,我需要過濾搜索結果以僅顯示在指定郵政編碼5英里範圍內的一個或多個位置可用的供應商(由Nominatim進行地理位置經度和緯度編碼)。

如果供應商只有一個關聯的位置,那麼使用django-haystack會很容易。我可以讓我的索引

class VendorIndex(indexes.SearchIndex, indexes.Indexable): 
    text = indexes.CharField(document=True, use_template=True) 
    location = indexes.LocationField(model_attr='location__point') 
    # Other fields 

和以下行添加到我的搜索形式的search()方法:

# Check to see if a start_date was chosen. 
    if self.cleaned_data['zip_code']: 
     location = self.geolocator.geocode(str(self.cleaned_data['zip_code']), timeout=10) 
     point = Point(location.longitude, location.latitude) 
     sqs = sqs.dwithin(
      'location', point, D(mi=settings.SEARCH_MILE_RADIUS), 
     ) 

問題是通過在其供應商可提供的所有地點搜索。在Geodjango查詢中,我只能將位置表示爲多點...但乾草堆僅支持單點對象。我不需要查找位於5英里範圍內的供應商地點數量,我只需要過濾掉所有不包含至少一個位於輸入位置所需距離內的位置的供應商。

必須有某種方法可以實現這個目標嗎?

的elasticsearch空間查詢文檔包含下面的註釋:

多位置每個文檔

的geo_distance過濾器可以每 文檔的多個位置點的工作。一旦一個地點與過濾器匹配, 文檔將包含在過濾器中。

因此顯然elasticsearch可以支持我想要做的事情。現在我需要知道乾草堆是否也可以支持這一點,或者如果我需要圍繞乾草堆進行一些黑客攻擊。

回答

1

所以我通過創建一個自定義字段類型來處理多個地點的解決了這個問題。

如果其他人需要django-haystack的單個模型實例的多個位置,就像我一樣,可以從github下載this gist以使用MultiLocationField。它確實適用於elasticsearch後端。我對其他後臺不積極。

半相關:

還要注意的是有一個臭蟲在Django的草垛與包括計算距離elasticsearch。當您使用D(mi = 10)指定距離(顯然,您可以選擇單位和距離,mi和10只是佔位符)時,django-haystack會將其轉換爲km,然後將其作爲距離參數發送給elasticsearch,而不指定單位。由於彈性搜索的默認距離單位是米,因此elasticsearch將此km距離解釋爲米,因此將關閉因子1000。我花了很長時間試圖弄清楚我的代碼出了什麼問題,然後才意識到這是一個錯誤。當我真的想要5公里的距離時,我通過做類似於D(km = 5000)的東西來繞過它。不知道爲什麼django-haystack不只是快速修改這個bug。

+0

正是我需要:)謝謝。我相信你提到的錯誤已經被[固定](https://github.com/django-haystack/django-haystack/pull/1003/) 你真的設法使用這個字段嗎?你有沒有得到你修正的錯誤,但不在要點中?你有沒有考慮過把這個領域的公關發給'django-haystack'? – 2016-06-29 10:58:33

+0

我發現了一些問題,並且[改進了它](https://gist.github.com/browniebroke/b4767dcce10ce0910ce53c8d102cfc57)。 – 2016-06-29 11:28:37

+1

如果我沒有記錯的話,這個領域正在爲我工​​作,因爲我想要它,但是我在一年半前使用了它,所以我不記得確定。看看這些代碼,以及你所做的改變,我看不出它會如何爲我工作。從未將公關提交給django-haystack – rfj001 2016-06-29 15:14:56

0

想要GeoDjango!草垛是全文搜索

https://docs.djangoproject.com/en/dev/ref/contrib/gis/

http://postgis.net/

然後,你可以使用Django的QuerySet的語法,這樣一個從文檔其中「發現5英里內的所有郵編表達地理空間查詢一些點「:

Zipcode.objects.filter(poly__distance_lt=(some_point, Distance(m=5))) 

#^from https://docs.djangoproject.com/en/dev/ref/contrib/gis/geoquerysets/#distance-lookups 
+0

嗯是的......但我正在通過基於多個搜索標準的大量對象進行搜索,需要分面,並且還需要按位置過濾。這是一個相當搜索密集的應用程序。不會使用Geodjango查詢會產生很多數據庫開銷? – rfj001 2014-12-04 07:38:17