我正在使用Firebase来存储用户上次扫描的纬度和经度。
条目如下所示:
"Bdhwu37Jdmd28DmenHahd221" : {
"country_code" : "at",
"firstname" : "John",
"gender" : "m",
"lat" : 11.2549387,
"lon" : 17.3419559
}
每当用户按下特定的"搜索"按钮,我希望我的Firebase功能可以获取离发送请求的人最近的人。
由于Firebase只允许在一个字段后查询,因此我决定添加country_code,以便对该字段进行一些范围限制和查询。但是,当我加载特定国家/地区的每个用户,然后检查给定用户与同一国家/地区的所有其他用户之间的最小距离时,它仍然非常慢。
已经有5个用户,该功能需要40秒才能达到效果。
我也读过有关复合索引的内容,但我需要以某种方式结合纬度和经度并查询这两个字段。
有没有办法让这里涉及第二个和第三个查询(例如搜索相同的country_code,然后搜索类似的经度和纬度)或者我必须在我的服务器代码中解决这个问题吗?
答案 0 :(得分:22)
Firebase数据库只能通过单个属性进行查询。因此,过滤纬度和经度值的方法是将它们组合成单个属性。组合属性必须保留数字值所需的过滤特性,例如过滤范围的能力。
虽然这看起来似乎不太可能,但它实际上是以Geohashes的形式完成的。其中一些特点:
它是一种分层空间数据结构,它将空间细分为网格形状的桶
所以:Geohashes将空间划分为一个桶网格,每个桶由一个字符串标识。
Geohashes提供了任意精度等属性,并且可以逐渐从代码末尾删除字符以减小其大小(并逐渐失去精度)。
字符串越长,桶覆盖的面积越大
由于逐渐精确度降低,附近的地方通常会(但不总是)出现类似的前缀。共享前缀越长,两个位置越接近。
以相同字符开头的字符串彼此接近。
结合这些特征,您可以看到为什么这些Geohashes对于使用Firebase数据库非常有吸引力:它们将位置的纬度和经度组合成单个字符串,其中按字典顺序排列的字符串指向的位置在物理上彼此靠近。魔术!
Firebase提供了一个名为Geofire的库,它使用Geohashes在其实时数据库之上实现Geolocation系统。该库可用于JavaScript,Java和Objective-C/Swift。
要了解有关Geofire的更多信息,请查看: