【问题标题】:How would I query the most recent, nearby Geopoints in a Firestore database?如何查询 Firestore 数据库中最近的、附近的地理点?
【发布时间】:2018-09-06 10:29:09
【问题描述】:

如何获取 Firestore 中按时间排序的地理位置半径中的最新文档?

我有一个解决方案来获取指定地理位置半径内的 Firestore 数据库中的所有文档。

我需要这些按时间排序。正如您想象的那样,在洛杉矶这样的地方,附近可能有 10,000 个帖子,而我目前的解决方案无法扩展。

这是我在 SWIFT 4 中的 Firestore 查询:

var query = docRef.whereField("geo", isGreaterThan: lesserGeopoint).whereField("geo", isLessThan: greaterGeopoint) 

这足以让我获得最近的帖子。所以,一旦我有了所有最接近的帖子,我就会解析它们并将它们放入一个数组中,然后按如下方式对数组进行排序:

self.posts.sort(by: { $0.time > $1.time }) 

这可行,但是,我使用虚拟数据进行了规模测试,结果如下:

(N = amount of posts that are queried and loaded)

N               LOAD TIME (average)
-----------------------------------
0               303 ms
1               323 ms
100             393 ms
500             637 ms
1000            1011 ms (1 second)
5000            10439 ms (10.4 seconds) 

任何超过 1,000 个附近帖子的内容都不实用。我也不能将查询限制为 1000 个文档,因为它没有在 Firestore 服务器上按时间排序,所以它只需要附近的 1000 个随机文档,然后按时间排序。但是可能有一个更新的帖子没有进入该批次。

我如何找到一种解决方案来获取最近的、附近的帖子,并限制查询以便我的应用可以扩展。

【问题讨论】:

  • 听说过 GeoFire?听起来像是实时数据库的用例?
  • @RonRoyston 我已经多次使用 GeoFire。我的问题是要求 Firestore 的解决方案,而不是实时数据库。另外,我不完全确定您是否阅读了这个问题。 Geofire 仅用于地理查询,不支持按时间戳排序和限制。

标签: swift firebase google-cloud-firestore


【解决方案1】:

您应该能够通过使用时间字段进行排序并设置返回文档数量的限制来实现此目的。

第一个 .whereField 必须包含第一个 orderBy 字段(在您的情况下为 time)。在您的地理查询参数之后,按时间字段排序,然后设置(例如)10 的 limit,以获得前 10 个结果。

query = docRef.whereField("time", isGreaterThan: 0).whereField("geo", isGreaterThan: lesserGeopoint).whereField("geo", isLessThan: greaterGeopoint).order(by: "time").limit(to:10)

如果您将时间存储为 Cloud Firestore 原生时间戳 (ISO8601),则需要使用 whereField("time", isGreaterThan: "")

更新

此特定解决方案不起作用,因为您无法对 Simple and Compound Queries - Query Limitations 中所述的 2 个单独字段执行范围查询

【讨论】:

  • 问题是,无论出于何种原因,Firebase 都不允许我们在不是我们进行比较的字段上调用 ​​orderBy。例如,由于我在“geo”字段上进行了比较,我无法按时间排序。很沮丧,我知道
  • 这就是您在查询开始时为时间字段添加 .whereField 的原因。它不需要过滤任何东西。它只需要返回所有文档,因此 >0 或 >""
  • 刚刚注意到,非常感谢。你是这方面的天才。
  • 'InvalidQueryException', reason: 'Invalid Query. All where filters with an inequality (lessThan, lessThanOrEqual, greaterThan, or greaterThanOrEqual) must be on the same field. But you have inequality filters on 'timestamp' and 'geo'' 一个新错误。我猜所有的不等式 WHERE 子句都需要在同一个字段上。
  • 我一直在考虑这个问题。如果您使用Map of Values 解决方案添加一个包含城市(键)和时间戳(值)的location 对象,您可以获取按时间戳排序的城市的所有文档。然后您可以按更精确的地理点进行过滤。不理想,我知道。或者,如果您的地理位置是固定的,您可以使用 Cloud Functions 将数据写入 BigQuery 之类的东西,然后从那里请求。
猜你喜欢
  • 1970-01-01
  • 2021-01-05
  • 2018-03-19
  • 2016-05-02
相关资源
最近更新 更多