【问题标题】:Is it possible to query Firebase Firestore by both a location and age range?是否可以同时按位置和年龄范围查询 Firebase Firestore?
【发布时间】:2022-06-30 15:57:42
【问题描述】:

如何根据年龄范围和位置查询我的 Firestore 数据库。

例如,假设我想获取年龄在 18 到 30 岁之间且距离我 5 英里以内的所有用户。

这是我当前数据库结构的简化版本。

users
  uid_0
    age: 21
  uid_1
    age: 24

要按年龄参数过滤,我知道我可以这样做:

// Swift

db.collection("users")
  .whereField("age", isGreaterThanOrEqualTo: 18)
  .whereField("age", isLessThanOrEqualTo: 30)

对于位置,我读过geofire可以使用,这会添加一个额外的节点,例如:

_geofire
  uid_0:
    g: "asdaseeefef"
    l: 
      0: 52.2101515118818
      1: -0.3215188181881
  uid_1:
    g: "oposooksok"
    l: 
      0: 50.1234567898788
      1: -0.8789999595988

但我不确定如何在我原来的性别+年龄查询之上添加位置查询(我不确定如何单独进行位置查询)。但关于将两者结合起来,我主要担心的是 Firestore 文档指定您只能在一个字段上应用范围过滤器,而我已经为 age 字段应用了一个。

是否可以按位置过滤同时按年龄范围过滤?

我还查看了 Firestore 的 geo queries,它看起来有些有希望,但理解起来却相当混乱,所以我不确定这是否会有同样的限制。

【问题讨论】:

  • 地理查询不使用任何 where 语句,因为geofire 已经为您提供了您需要查找的所有地理哈希,所以我会说您可以将它们组合起来.

标签: swift firebase google-cloud-firestore


【解决方案1】:

为了使用地理查询,您必须store the geohash 而不是纬度和经度才能查询它。

// Compute the GeoHash for a lat/lng point
let latitude = 51.5074
let longitude = 0.12780
let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let hash = GFUtils.geoHash(forLocation: location)

//Then store 'hash' in the user document as 'geohash'

然后,如果您将其存储在具有年龄字段的同一用户文档中,则最终查询应如下所示。

// Find users within 5km of me.
let center = CLLocationCoordinate2D(latitude: 51.5074, longitude: 0.1278) //Your position
let radiusInM: Double = 5 * 1000 //You may need to convert it to meters if you have it in miles

// Each item in 'bounds' represents a startAt/endAt pair. We have to issue
// a separate query for each pair. There can be up to 9 pairs of bounds
// depending on overlap, but in most cases there are 4.
let queryBounds = GFUtils.queryBounds(forLocation: center,
                                      withRadius: radiusInM)
let queries = queryBounds.map { bound -> Query in
    return db.collection("users")
        .whereField("age", isGreaterThanOrEqualTo: 18)
        .whereField("age", isLessThanOrEqualTo: 30)
        .order(by: "geohash")
        .start(at: [bound.startValue])
        .end(at: [bound.endValue])
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    相关资源
    最近更新 更多