2013-03-06 57 views
6

我在GAE Search索引中有約400,000個文檔。所有文件都有一個locationGeoPoint財產,並分佈在整個地球。有些文件可能距離任何其他文件超過4000公里,其他文件可能在彼此的米之內。如何使用Google App Engine搜索API找到最接近的文檔?

我想找到最接近的文件一組特定的座標,但發現下面的代碼會產生不正確的結果:

from google.appengine.api import search 

# coords are in the form of a tuple e.g. (50.123, 1.123) 
search.Document(
    doc_id='meaningful-unique-id', 
    fields=[search.GeoField(name='location' 
          value=search.GeoPoint(coords[0], coords[1]))]) 

# find document function radius is in metres 
def find_document(coords, radius=1000000): 
    sort_expr = search.SortExpression(
     expression='distance(location, geopoint(%.3f, %.3f))' % coords, 
     direction=search.SortExpression.ASCENDING, 
     default_value=0) 

    search_query = search.Query(
     query_string='distance(location, geopoint(%.3f, %.3f)) < %d' \ 
        % (coords[0], coords[1], radius), 
     options=search.QueryOptions(
      limit=1, 
      ids_only=True, 
      sort_options=search.SortOptions(expressions=[sort_expr]))) 

    index = search.Index(name='document-index') 
    return index.search(search_query) 

有了這個代碼,我會得到的結果是一致的,但不正確。例如,搜尋倫敦最近的文件顯示最近的文件是在蘇格蘭。我已經證實有數千個更接近的文件。

我把問題縮小到radius參數太大。如果半徑下降到12公里左右(radius=12000),我會得到正確的結果。在12公里範圍內通常不會有超過1000個文件。 (可能與search.SortOptions(limit=1000)有關。)

的問題是,如果我在地球上的某個區域稀疏那裏有沒有千里的任何文件,我的搜索功能將不能與radius=12000(12公里)返回任何東西。無論我在哪裏,我都希望它將最接近的文檔返回給我。如何通過一次調用Search API來實現這一點?

回答

5

我認爲問題如下。 您的查詢將選擇最多10K文件,然後這些文件將根據您的距離排序表達式進行排序並返回。 (也就是說,這種排序實際上並不是所有的400k文件。) 所以我懷疑這個10k選擇中沒有包含一些地理上較近的點。 這就是爲什麼當您縮小搜索半徑時事情會更好,因爲您在該半徑中的總積分較少。

從本質上講,您希望將查詢的「點擊次數」降低到10k,這對於您查詢的內容是有意義的。 可以在至少幾個方法,你可以結合起來解決這個問題:

  • 添加一個排名,讓最「重要」的文檔(通過某些標準是有道理的在你的域)在返回等級順序,然後這些將按距離排序。
  • 過濾一個或多個文檔字段(例如,'業務類別',如果您的文檔包含有關企業的信息)以減少候選文檔的數量。

(我不相信這個10k閾值目前在Search API文檔中;我已經提交了一張票來獲得它)。

+0

感謝您確認@Middy和我推測在幕後發生了什麼。知道'命中'限制是10k肯定有幫助。爲了完成,我將陳述答案**我希望它能夠將最接近的文檔返回給我,無論我身在何處。我怎樣才能實現這一致的調用Search API?**是我不能一致如果我的搜索半徑_might_包含超過10k文件 - 不幸的是我的應用程序可能會做:( – Dan 2013-03-13 21:00:12

1

我有完全相同的問題,我不認爲它是可能的。問題發生在你自己發現有更多可能的結果比返回的結果時。 Google算法會在加載限制時退出,然後對結果進行排序。

我已經看到了與您及其搜索API的相同部分。

One Hack將把您的搜索細分爲子扇區,同時進行多個呼叫,然後合併並排序結果。

+0

從實用的角度來看,如果你知道你最密集的'GeoPoint'簇可能是多麼密集的話,黑客就可以工作。 (以Search API配額爲代價)。但是,如果您不知道最密集的集羣有多密集,那麼在您不知情的情況下,子行業可能會遭遇出現錯誤結果的相同問題。在我的情況下,每天有20,000個Search API調用沒有留下太多空間讓每個用戶請求的呼叫數加倍。 – Dan 2013-03-11 22:56:13

0

瘋狂的想法,爲什麼不保留/記錄3點的距離,然後從中計算出來。

相關問題