【问题标题】:How can I find the closest document using Google App Engine Search API?如何使用 Google App Engine Search API 找到最近的文档?
【发布时间】:2013-02-21 16:40:21
【问题描述】:

GAE Search 索引中有大约 400,000 个文档。所有文档都有一个locationGeoPoint 属性,并且分布在全球各地。一些文件可能与任何其他文件相距超过 4000 公里,而另一些文件可能彼此相距几米。

我想找到最接近特定坐标集的文档,但发现以下代码给出了错误的结果:

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 始终如一地完成此任务?

【问题讨论】:

    标签: google-app-engine python-2.7 gae-search


    【解决方案1】:

    我有完全相同的问题,我认为不可能。当您自己发现可能的结果多于返回的结果时,就会出现问题。谷歌算法在加载限制后退出,然后对结果进行排序。

    我已经看到了与您相同的集群及其搜索 API 的一部分。

    一个技巧是将您的搜索细分为子部门,同时进行多个调用,然后合并和排序结果。

    【讨论】:

    • 从实用的角度来看,如果您知道GeoPoints 最密集的集群可能有多密集,那么该hack 将起作用。 (以搜索 API 配额为代价。)但是,如果您不知道最密集的集群有多密集,那么子扇区可能会遇到同样的问题,即在您不知情的情况下给出错误的结果。在我的例子中,每天 20,000 次搜索 API 调用并没有为每个用户请求的加倍调用留下太多空间。
    【解决方案2】:

    好主意,为什么不保留/记录 3 点的距离,然后据此计算。

    【讨论】:

      【解决方案3】:

      我认为问题如下。 您的查询将选择最多 10K 个文档,然后根据您的距离排序表达式对这些文档进行排序并返回。 (也就是说,排序实际上并不是对所有 400k 文档进行排序。) 所以我怀疑一些地理上更接近的点不包括在这个 10k 选择中。 这就是缩小搜索半径时效果更好的原因,因为该半径内的总点数较少。

      基本上,您希望以一种对您查询的内容有意义的方式将您的查询“命中”降低到 10k。 您可以通过至少几种方式来解决这个问题,您可以将它们组合起来:

      • 添加排名,以便按排名顺序返回最“重要”的文档(根据您的域中有意义的某些标准),然后这些文档将按距离排序。
      • 过滤一个或多个文档字段(例如,“业务类别”,如果您的文档包含有关企业的信息)以减少候选文档的数量。

      (我不相信搜索 API 文档中目前没有这个 10k 阈值;我已经提交了一张票以添加它)。

      【讨论】:

      • 感谢您确认@Middy 和我认为幕后发生的事情。知道“命中”限制是 10k 肯定会有所帮助。为了完成,我将说明的答案,无论我身在何处,我都希望它能够将最近的文档返回给我。如何通过一次调用 Search API 来始终如一地完成此任务? 如果我的搜索半径可能包含超过 10k 的文档,我不能始终如一地 - 不幸的是我的应用程序可能会这样做: (
      猜你喜欢
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多