查询附近的位置

Posted

技术标签:

【中文标题】查询附近的位置【英文标题】:Query for nearby locations 【发布时间】:2017-09-07 13:15:57 【问题描述】:

我正在使用 Firebase 来存储用户上次扫描的纬度和经度。

条目如下所示:

"Bdhwu37Jdmd28DmenHahd221" : 
  "country_code" : "at",
  "firstname" : "John",
  "gender" : "m",
  "lat" : 11.2549387,
  "lon" : 17.3419559

每当用户按下特定的“搜索”按钮时,我希望我的 Firebase 功能能够获取离发送请求的人最近的人。

由于 Firebase 仅允许在一个字段后进行查询,因此我决定添加 country_code,以对该字段进行一些范围限制和查询。但是当我加载特定国家/地区的每个用户然后检查给定用户与同一国家/地区的所有其他用户之间的最小距离时,它仍然非常慢。

已经有 5 个用户,该功能需要大约 40 秒才能达到结果。

我也读过复合索引,但我需要以某种方式结合纬度和经度并查询这两个字段。

有什么方法可以在这里获得第二个和第三个查询(例如搜索相同的国家代码,然后搜索相似的经度和纬度)还是我必须在我的服务器代码中解决这个问题?

【问题讨论】:

github.com/firebase/geofire 【参考方案1】:

Firebase 数据库只能通过单个属性进行查询。所以过滤纬度和经度值的方法是将它们组合成一个属性。该组合属性必须保留您想要的数值过滤特征,例如过滤范围的能力。

虽然起初这似乎是不可能的,但实际上它是以Geohashes 的形式完成的。它的一些特点:

    它是一种分层的空间数据结构,将空间细分为网格形状的桶

所以:Geohashes 将空间划分为一个桶网格,每个桶由一个字符串标识。

    Geohashes 提供任意精度等属性,以及逐渐从代码末尾删除字符以减小其大小(并逐渐失去精度)的可能性。

字符串越长,桶覆盖的区域越大

    由于精度逐渐下降,附近的地方经常(但不总是)出现相似的前缀。共享前缀越长,两个地方越接近。

以相同字符开头的字符串彼此接近。

结合这些特征,您就会明白为什么这些 Geohashes 如此适合与 Firebase 数据库一起使用:它们将一个位置的纬度和经度组合成一个字符串,其中按字典顺序相互接近的字符串指向的位置物理上彼此接近。魔法!

Firebase 提供了一个名为 Geofire 的库,它使用 Geohashes 在其实时数据库之上实现地理定位系统。该库适用于javascript、Java 和Objective-C/Swift。

要了解有关 Geofire 的更多信息,请查看:

这个blog post introducing Geofire 2 demo app that used to show local busses moving on a map。该应用不再工作(数据未更新),但代码仍然可用。 video 和 documentation 介绍如何在 Cloud Firestore 上实施地理查询。

【讨论】:

谢谢,我会阅读并尝试这个。有没有可能,云功能超级慢?每次只查询 3 个人就需要 40 秒(不仅是第一次),而且我只访问 2 个数据库。 如果您一直认为性能不合理(即使您认为 Cloud Functions 处于测试阶段),请通过minimal code that reproduces that problem 提出问题。 GeoFire 工作正常,但当用户的位置嵌套在用户数据中时,我无法使其工作。我的 geoFire 参考点位于“/user”,我的 geoFire 数据位于 /user/$uid/location,geoFire 会自动搜索嵌套字段还是我必须在某个地方定义“g”值所在的位置?似乎该算法正在我的“/user”条目下方而不是“位置”处寻找“g” 使用 Geofire 时,您总是会得到一个单独的地理索引。该位置纯粹将位置映射到键(反之亦然)。您的实际用户数据将在数据库中的其他位置,您应该加载它,因为键进入您的查询范围并再次保留它。 现在可以使用了,非常感谢。现在速度也还好,大概花了这么久,因为我没有正确实现:)

以上是关于查询附近的位置的主要内容,如果未能解决你的问题,请参考以下文章

团购网站上想要查询别的位置 附近的商家怎样可以查看?我现在只能查看我附近的商家我还没有到那个位置?

此查询的 MySQL 确切语法:查找附近的位置

Android:从firebase查询附近的位置

带有位置数据的大型 MySQL 数据库(21MM 记录) - 每个位置都有经纬度 - 需要运行“附近”查询

获取附近位置的最佳方法?

在特定角度的位置附近查找 - 在圆形查询中只考虑前面的半圈而不是后面