我想查询存储在名为“Users”的集合中的用户。每个用户都有年龄和体重等字段。有没有一种方法可以通过与使用 GeoFire 运行搜索的用户的距离来查询用户,并将其与 FireStore 搜索查询相结合?例如,我是一个用户,他正在寻找半径为 20 英里的人,但也想找到比他们年轻或年长 2 岁的人。
1 回答
Firestore 数据库可以过滤多个字段,但它只能对其中一个字段进行范围过滤。所以这个查询是可能的:
collection.where("age", ">", 18).where("age", "<", 20)
但这是不可能的:
// !!!THIS WON'T WORK!!!
collection.where("latitude", ">", 18.001).where("longitude", "<", 21.312)
我所知道的 GeoFirestore 库都使用 geohashes(在原始 GeoFire 库中使用)能够在底层数据库上做一些看似不可能的事情:根据纬度和经度过滤地理范围内的文档。
Geohashes 通过将位置的纬度和经度组合成单个字符串值来发挥其魔力,可以以不同程度的准确度对其进行过滤。这是可能的,因为您可以(某种程度上)表达一个经度与一个纬度的关系。因此,您可以将 lat 和 lon 的数字压缩合并为一个值,该值具有每个第一位的最高有效数字。
现在这也解释了为什么您不能简单地向地理查询添加另一个范围过滤器。你必须找到一种用距离来表达年龄差异的方法。如果你能做到这一点,那就“只是”将额外信息编码到地理年龄哈希中的问题。这对我来说听起来很复杂,但至少是可能的。
第一个问题是虽然没有通用方法将附加属性与纬度和经度相关联,这就是为什么您将自己解决这个问题的原因。我的直觉是大多数开发人员放弃了这个要求,或者在客户端进行了额外的排序/过滤。
如果您想向 geohash 添加相等过滤器(例如,特定地理范围内正好 18 岁的人的文档),这在 Firestore 级别上绝对是可能的,尽管我不知道 GeoFirestore 库是否公开了底层查询这样做的能力。
我强烈建议您学习更多有关该主题的内容,因为它非常引人入胜。一些资料来源:
- 如果您想详细了解为什么 Firestore 只能在单个字段上进行范围过滤,请观看来自“了解 Cloud Firestore”系列的视频。
- 如果您想了解有关geohashes、geoqueries 以及如何在 Firestore 上实现它们的更多信息,请观看我关于该主题的讨论。
- geohashes的维基百科解释。
我还建议查看有关该主题的这些先前的问题:
其中许多是关于(原始)Firebase 实时数据库的 GeoFire,但同样的原则也适用于 Firestore。